def test_next_route(): amount = UNIT_TRANSFER_AMOUNT channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) msg = 'an initialized state must use the first valid route' assert state.initiator.channel_identifier == channel1.identifier, msg assert not state.cancelled_channels state_change = ActionCancelRoute( UNIT_REGISTRY_IDENTIFIER, channel1.identifier, available_routes, ) iteration = initiator_manager.state_transition( state, state_change, channel_map, pseudo_random_generator, block_number, ) # HOP3 should be ignored because it doesnt have enough balance assert iteration.new_state.cancelled_channels == [channel1.identifier]
def test_events_for_close_secret_unknown(): """ Channel must not be closed when the unsafe region is reached and the secret is not known. """ amount = 3 block_number = 10 expiration = block_number + 30 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) state = TargetTransferState(from_route, from_transfer) events = target.events_for_close(state, from_channel, expiration) assert not events
def test_init_with_maximum_pending_transfers_exceeded(): channel1 = factories.make_channel( our_balance=2 * MAXIMUM_PENDING_TRANSFERS * UNIT_TRANSFER_AMOUNT, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] pseudo_random_generator = random.Random() transitions = list() block_number = 1 for _ in range(MAXIMUM_PENDING_TRANSFERS + 1): init_state_change = ActionInitInitiator(make_transfer_description(), available_routes) transitions.append(initiator_manager.state_transition( None, init_state_change, channel_map, pseudo_random_generator, block_number, )) failed_transition = transitions.pop() assert all( isinstance(transition.new_state, InitiatorPaymentState) for transition in transitions ) assert failed_transition.new_state is None assert len(failed_transition.events) == 1 assert isinstance(failed_transition.events[0], EventPaymentSentFailed)
def make_from_route_from_counter(counter): from_channel = factories.make_channel( partner_balance=next(counter), partner_address=factories.HOP1, token_address=factories.make_address(), channel_identifier=next(counter), ) from_route = factories.route_from_channel(from_channel) expiration = factories.UNIT_REVEAL_TIMEOUT + 1 from_transfer = factories.make_signed_transfer_for( from_channel, factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( balance_proof=factories.BalanceProofProperties( transferred_amount=0, token_network_identifier=from_channel.token_network_identifier, ), amount=1, expiration=expiration, secret=sha3(factories.make_secret(next(counter))), initiator=factories.make_address(), target=factories.make_address(), payment_identifier=next(counter), ), sender=factories.HOP1, pkey=factories.HOP1_KEY, ), ) return from_route, from_transfer
def test_channel_settle_must_properly_cleanup(): open_block_number = 10 pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) amount = 30 our_balance = amount + 50 channel_state = factories.make_channel(our_balance=our_balance) channel_new_state_change = ContractReceiveChannelNew(token_network_id, channel_state) channel_new_iteration = token_network.state_transition( token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( token_network_id, channel_state.identifier, channel_state.partner_state.address, closed_block_number, ) channel_closed_iteration = token_network.state_transition( channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( token_network_id, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert channel_state.identifier not in ids_to_channels
def test_contract_receive_channelnew_must_be_idempotent(): block_number = 10 pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) payment_network_identifier = factories.make_payment_network_identifier() amount = 30 our_balance = amount + 50 channel_state1 = factories.make_channel(our_balance=our_balance) channel_state2 = copy.deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_id, channel_state1, block_number, ) token_network.state_transition( payment_network_identifier, token_network_state, state_change1, pseudo_random_generator, block_number, ) state_change2 = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_id, channel_state2, block_number + 1, ) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( payment_network_identifier, token_network_state, state_change2, pseudo_random_generator, block_number, ) msg = 'the channel must not have been overwritten' channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channelidentifiers partner_channels_ids = channelmap_by_address[channel_state1.partner_state.address] assert channel_state1.identifier in partner_channels_ids, msg
def test_contract_receive_channelnew_must_be_idempotent(): block_number = 10 pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) amount = 30 our_balance = amount + 50 channel_state1 = factories.make_channel(our_balance=our_balance) channel_state2 = copy.deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew(token_network_id, channel_state1) token_network.state_transition( token_network_state, state_change1, pseudo_random_generator, block_number, ) # change the existing channel payment_identifier = 1 message_identifier = random.randint(0, UINT64_MAX) channel.send_directtransfer( channel_state1, amount, message_identifier, payment_identifier, ) state_change2 = ContractReceiveChannelNew(token_network_id, channel_state2) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( token_network_state, state_change2, pseudo_random_generator, block_number, ) msg = 'the channel must not been overwritten' channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channels assert channelmap_by_address[channel_state1.partner_state.address] == channel_state1, msg
def test_handle_inittarget(): """ Init transfer must send a secret request if the expiration is valid. """ amount = 3 block_number = 1 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET pseudo_random_generator = random.Random() from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer( amount, initiator, target_address, expiration, UNIT_SECRET, channel_identifier=from_channel.identifier, ) state_change = ActionInitTarget( from_route, from_transfer, ) iteration = target.handle_inittarget( state_change, from_channel, pseudo_random_generator, block_number, ) events = iteration.events assert events assert isinstance(events[0], SendSecretRequest) assert events[0].payment_identifier == from_transfer.payment_identifier assert events[0].amount == from_transfer.lock.amount assert events[0].secrethash == from_transfer.lock.secrethash assert events[0].recipient == initiator
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.make_channel( our_balance=1000, partner_balance=1000, token_network_identifier=self.token_network_id, our_address=self.address, partner_address=partner_address, ) return partner_address
def netting_channel_state(chain_state, token_network_state, payment_network_state): partner = factories.make_address() channel_id = factories.make_channel_identifier() channel_state = factories.make_channel( our_balance=10, partner_balance=10, our_address=chain_state.our_address, partner_address=partner, token_address=token_network_state.token_address, payment_network_identifier=payment_network_state.address, token_network_identifier=token_network_state.address, channel_identifier=channel_id, ) 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_events_for_onchain_secretreveal(): """ Secret must be registered on-chain when the unsafe region is reached and the secret is known. """ amount = 3 block_number = 10 expiration = block_number + 30 initiator = HOP1 target_address = UNIT_TRANSFER_TARGET from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) channel.register_secret(from_channel, UNIT_SECRET, UNIT_SECRETHASH) safe_to_wait = expiration - from_channel.reveal_timeout - 1 unsafe_to_wait = expiration - from_channel.reveal_timeout state = TargetTransferState(from_route, from_transfer) events = target.events_for_onchain_secretreveal(state, from_channel, safe_to_wait) assert not events events = target.events_for_onchain_secretreveal(state, from_channel, unsafe_to_wait) assert events assert isinstance(events[0], ContractSendSecretReveal) assert events[0].secret == UNIT_SECRET
def test_init_with_usable_routes(): channel1 = factories.make_channel( our_balance=UNIT_TRANSFER_AMOUNT, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] pseudo_random_generator = random.Random() init_state_change = ActionInitInitiator( factories.UNIT_TRANSFER_DESCRIPTION, available_routes, ) block_number = 1 transition = initiator_manager.state_transition( None, init_state_change, channel_map, pseudo_random_generator, block_number, ) assert isinstance(transition.new_state, InitiatorPaymentState) assert transition.events, 'we have a valid route, the mediated transfer event must be emitted' payment_state = transition.new_state assert payment_state.initiator.transfer_description == factories.UNIT_TRANSFER_DESCRIPTION mediated_transfers = [e for e in transition.events if isinstance(e, SendLockedTransfer)] assert len(mediated_transfers) == 1, 'mediated_transfer should /not/ split the transfer' send_mediated_transfer = mediated_transfers[0] transfer = send_mediated_transfer.transfer expiration = initiator.get_initial_lock_expiration(block_number, channel1.reveal_timeout) assert transfer.balance_proof.token_network_identifier == channel1.token_network_identifier assert transfer.lock.amount == factories.UNIT_TRANSFER_DESCRIPTION.amount assert transfer.lock.expiration == expiration assert transfer.lock.secrethash == factories.UNIT_TRANSFER_DESCRIPTION.secrethash assert send_mediated_transfer.recipient == channel1.partner_state.address
def setup_initiator_tests( amount=UNIT_TRANSFER_AMOUNT, partner_balance=EMPTY, our_address=EMPTY, partner_address=EMPTY, block_number=1, ) -> InitiatorSetup: """Commonly used setup code for initiator manager and channel""" prng = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=partner_balance, our_address=our_address, partner_address=partner_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, prng, block_number, ) lock = channel.get_lock( channel1.our_state, current_state.initiator.transfer_description.secrethash, ) setup = InitiatorSetup( current_state=current_state, block_number=block_number, channel=channel1, channel_map=channel_map, available_routes=available_routes, prng=prng, lock=lock, ) return setup
def test_handle_inittarget_bad_expiration(): """ Init transfer must do nothing if the expiration is bad. """ block_number = 1 amount = 3 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET pseudo_random_generator = random.Random() from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) state_change = ActionInitTarget(from_route, from_transfer) iteration = target.handle_inittarget( state_change, from_channel, pseudo_random_generator, block_number, ) assert must_contain_entry(iteration.events, EventUnlockClaimFailed, {})
def make_target_state(our_address, amount, block_number, initiator, expiration=None): from_channel = factories.make_channel( our_address=our_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) if expiration is None: expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, our_address, expiration, UNIT_SECRET, ) state = TargetTransferState(from_route, from_transfer) return from_channel, state
def test_routing_issue2663( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 open_block_number_hash = factories.make_block_hash() pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, 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(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_number_hash, ) 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(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) 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(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) 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 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address1 # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_UNREACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_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: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_UNREACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address1 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].node_address == address1 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address1
def test_routing_updates( token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address1, ) payment_network_identifier = factories.make_payment_network_identifier() open_block_hash = factories.make_block_hash() # create a new channel as participant, check graph update channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_hash, ) graph_state = channel_new_iteration1.new_state.network_graph assert channel_state.identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 1 assert graph_state.network[our_address][address1] is not None assert len(graph_state.network.edges()) == 1 # create a new channel without being participant, check graph update new_channel_identifier = factories.make_channel_identifier() channel_new_state_change = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) graph_state = channel_new_iteration2.new_state.network_graph assert channel_state.identifier in graph_state.channel_identifier_to_participants assert new_channel_identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 2 assert graph_state.network[our_address][address1] is not None assert graph_state.network[address2][address3] is not None assert len(graph_state.network.edges()) == 2 # close the channel the node is a participant of, check edge is removed from graph closed_block_number = open_block_number + 20 closed_block_hash = factories.make_block_hash() channel_close_state_change1 = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration2.new_state, state_change=channel_close_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) # Check that a second ContractReceiveChannelClosed events is handled properly # This might have been sent from the other participant of the channel # See issue #2449 channel_close_state_change2 = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.our_state.address, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration1.new_state, state_change=channel_close_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) graph_state = channel_closed_iteration2.new_state.network_graph assert channel_state.identifier not in graph_state.channel_identifier_to_participants assert new_channel_identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 1 assert graph_state.network[address2][address3] is not None assert len(graph_state.network.edges()) == 1 # close the channel the node is not a participant of, check edge is removed from graph channel_close_state_change3 = ContractReceiveRouteClosed( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration2.new_state, state_change=channel_close_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number + 10, block_hash=factories.make_block_hash(), ) # Check that a second ContractReceiveRouteClosed events is handled properly. # This might have been sent from the second participant of the channel # See issue #2449 closed_block_plus_10_hash = factories.make_block_hash() channel_close_state_change4 = ContractReceiveRouteClosed( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, block_number=closed_block_number + 10, block_hash=closed_block_plus_10_hash, ) channel_closed_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration3.new_state, state_change=channel_close_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number + 10, block_hash=closed_block_plus_10_hash, ) graph_state = channel_closed_iteration4.new_state.network_graph assert channel_state.identifier not in graph_state.channel_identifier_to_participants assert new_channel_identifier not in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 0 assert len(graph_state.network.edges()) == 0
def test_multiple_channel_states( chain_state, token_network_state, our_address, ): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_hash, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) 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_route = factories.route_from_channel(channel_state) init_target = ActionInitTarget( from_route, mediated_transfer, ) 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, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), ) channel_settled_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) 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_state = factories.make_channel( our_balance=our_balance, partner_balance=our_balance, partner_address=address, ) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=new_channel_state, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_new_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_hash, ) 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_contract_receive_channelnew_must_be_idempotent(): block_number = 10 pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) payment_network_identifier = factories.make_payment_network_identifier() amount = 30 our_balance = amount + 50 channel_state1 = factories.make_channel(our_balance=our_balance) channel_state2 = copy.deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_id, channel_state1, block_number, ) token_network.state_transition( payment_network_identifier, token_network_state, state_change1, pseudo_random_generator, block_number, ) # change the existing channel payment_identifier = 1 message_identifier = random.randint(0, UINT64_MAX) channel.send_directtransfer( channel_state1, amount, message_identifier, payment_identifier, ) state_change2 = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_id, channel_state2, block_number + 1, ) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( payment_network_identifier, token_network_state, state_change2, pseudo_random_generator, block_number, ) msg = 'the channel must not been overwritten' channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channelidentifiers partner_channels_ids = channelmap_by_address[ channel_state1.partner_state.address] assert channel_state1.identifier in partner_channels_ids, msg
def test_multiple_channel_states( chain_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, channel_state, open_block_number, ) channel_new_iteration = token_network.state_transition( payment_network_identifier, token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) 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_route = factories.route_from_channel(channel_state) init_target = ActionInitTarget( from_route, mediated_transfer, ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_state.address, channel_state.identifier, closed_block_number, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier, channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( factories.make_transaction_hash(), token_network_state.address, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( payment_network_identifier, channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) 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_state = factories.make_channel( our_balance=our_balance, partner_balance=our_balance, partner_address=address, ) channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, new_channel_state, closed_block_number + 1, ) channel_new_iteration = token_network.state_transition( payment_network_identifier, token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) 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 create_square_network_topology( payment_network_state, token_network_state, our_address, ) -> typing.Tuple[ TokenNetworkState, typing.List[typing.Address], typing.List[NettingChannelState], ]: open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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 return ( channel_new_iteration4.new_state, [address1, address2, address3], (channel_state1, channel_state2), )
def test_initiator_lock_expired(): amount = UNIT_TRANSFER_AMOUNT * 2 block_number = 1 refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), ] block_number = 10 current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) transfer = current_state.initiator.transfer assert transfer.lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks # Trigger lock expiry state_change = Block( block_number=transfer.lock.expiration + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert events.must_contain_entry( iteration.events, SendLockExpired, { 'balance_proof': { 'nonce': 2, 'transferred_amount': 0, 'locked_amount': 0, }, 'secrethash': transfer.lock.secrethash, 'recipient': channel1.partner_state.address, }) assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Create 2 other transfers transfer2_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer2'), channel_map, pseudo_random_generator, 30, ) transfer2_lock = transfer2_state.initiator.transfer.lock transfer3_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer3'), channel_map, pseudo_random_generator, 32, ) transfer3_lock = transfer3_state.initiator.transfer.lock assert len(channel1.our_state.secrethashes_to_lockedlocks) == 2 assert transfer2_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks expiration_block_number = transfer2_lock.expiration + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK block = Block( block_number=expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( transfer2_state, block, channel_map, pseudo_random_generator, expiration_block_number, ) # Transfer 2 expired assert transfer2_lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Transfer 3 is still there assert transfer3_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks
def test_refund_transfer_next_route(): amount = UNIT_TRANSFER_AMOUNT our_address = factories.ADDR refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=our_address, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer refund_transfer = factories.make_signed_transfer( amount, our_address, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) assert channel1.partner_state.address == refund_address state_change = ReceiveTransferRefundCancelRoute( routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert iteration.new_state is not None route_cancelled = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) new_transfer = next(e for e in iteration.events if isinstance(e, SendLockedTransfer)) assert route_cancelled, 'The previous transfer must be cancelled' assert new_transfer, 'No mediated transfer event emitted, should have tried a new route' msg = 'the new transfer must use a new secret / secrethash' assert new_transfer.transfer.lock.secrethash != refund_transfer.lock.secrethash, msg assert iteration.new_state.initiator is not None
def test_payer_enter_danger_zone_with_transfer_payed(): """ A mediator may have paid the next hop (payee), and didn't get paid by the previous hop (payer). When this happens, an assertion must not be hit, because it means the transfer must be withdrawn on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ amount = 10 block_number = 5 target = HOP2 expiration = 30 payer_channel = factories.make_channel( partner_balance=amount, partner_address=UNIT_TRANSFER_SENDER, token_address=UNIT_TOKEN_ADDRESS, ) payer_transfer = factories.make_signed_transfer_for( payer_channel, amount, HOP1, target, expiration, UNIT_SECRET, ) channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, ) channelmap = { channel1.identifier: channel1, payer_channel.identifier: payer_channel, } possible_routes = [factories.route_from_channel(channel1)] mediator_state = MediatorTransferState(UNIT_HASHLOCK) initial_iteration = mediator.mediate_transfer( mediator_state, possible_routes, payer_channel, channelmap, payer_transfer, block_number, ) send_transfer = must_contain_entry(initial_iteration.events, SendMediatedTransfer, {}) assert send_transfer lock_expiration = send_transfer.transfer.lock.expiration new_state = initial_iteration.new_state for block_number in range(block_number, lock_expiration + 1): block_state_change = Block(block_number) block_iteration = mediator.handle_block( channelmap, new_state, block_state_change, block_number, ) new_state = block_iteration.new_state # send the balance proof, transitioning the payee state to paid assert new_state.transfers_pair[0].payee_state == 'payee_pending' receive_secret = ReceiveSecretReveal( UNIT_SECRET, channel1.partner_state.address, ) paid_iteration = mediator.state_transition( new_state, receive_secret, channelmap, block_number, ) paid_state = paid_iteration.new_state assert paid_state.transfers_pair[0].payee_state == 'payee_balance_proof' # move to the block in which the payee lock expires. This must not raise an # assertion expired_block_number = lock_expiration + 1 expired_block_state_change = Block(expired_block_number) block_iteration = mediator.handle_block( channelmap, paid_state, expired_block_state_change, expired_block_number, )
def test_channel_settle_must_properly_cleanup(): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) payment_network_identifier = factories.make_payment_network_identifier() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel(our_balance=our_balance) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_id, channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_hash, ) 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, token_network_identifier=token_network_id, channel_identifier=channel_state.identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_id, channel_identifier=channel_state.identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), ) channel_settled_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert channel_state.identifier not in ids_to_channels
def test_target_receive_lock_expired(): lock_amount = 7 block_number = 1 initiator = factories.HOP6 pseudo_random_generator = random.Random() our_balance = 100 our_address = factories.make_address() partner_balance = 130 from_channel = factories.make_channel( our_address=our_address, our_balance=our_balance, partner_address=UNIT_TRANSFER_SENDER, partner_balance=partner_balance, ) from_route = factories.route_from_channel(from_channel) expiration = block_number + from_channel.settle_timeout - from_channel.reveal_timeout from_transfer = factories.make_signed_transfer_for( from_channel, lock_amount, initiator, our_address, expiration, UNIT_SECRET, ) init = ActionInitTarget( from_route, from_transfer, ) init_transition = target.state_transition( None, init, from_channel, pseudo_random_generator, block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == from_route assert init_transition.new_state.transfer == from_transfer balance_proof = factories.make_signed_balance_proof( 2, from_transfer.balance_proof.transferred_amount, 0, from_transfer.balance_proof.token_network_identifier, from_channel.identifier, EMPTY_MERKLE_ROOT, from_transfer.lock.secrethash, sender_address=UNIT_TRANSFER_SENDER, private_key=UNIT_TRANSFER_PKEY, ) lock_expired_state_change = ReceiveLockExpired( HOP1, balance_proof, from_transfer.lock.secrethash, 1, ) iteration = target.state_transition( init_transition.new_state, lock_expired_state_change, from_channel, pseudo_random_generator, 10, ) assert must_contain_entry(iteration.events, SendProcessed, {}) assert iteration.new_state is None
def test_regression_mediator_task_no_routes(): """ The mediator must only be cleared after the waiting transfer's lock has been handled. If a node receives a transfer to mediate, but there is no route available (because there is no sufficient capacity or the partner nodes are offline), and a refund is not possible, the mediator task must not be cleared, otherwise followup remove expired lock messages wont be processed and the nodes will get out of sync. """ amount = 10 block_number = 5 target = HOP2 expiration = 30 pseudo_random_generator = random.Random() payer_channel = factories.make_channel( partner_balance=amount, partner_address=HOP2, token_address=UNIT_TOKEN_ADDRESS, ) payer_route = factories.route_from_channel(payer_channel) payer_transfer = factories.make_signed_transfer_for( payer_channel, amount, HOP1, target, expiration, UNIT_SECRET, pkey=HOP2_KEY, sender=HOP2, ) available_routes = [] channel_map = { payer_channel.identifier: payer_channel, } init_state_change = ActionInitMediator( available_routes, payer_route, payer_transfer, ) initial_state = None init_iteration = mediator.state_transition( initial_state, init_state_change, channel_map, pseudo_random_generator, block_number, ) msg = 'The task must not be cleared, even if there is no route to forward the transfer' assert init_iteration.new_state is not None, msg assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer assert must_contain_entry(init_iteration.events, SendLockedTransfer, {}) is None assert must_contain_entry(init_iteration.events, SendRefundTransfer, {}) is None secrethash = UNIT_SECRETHASH lock = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash] # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=payer_channel.partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=payer_channel.chain_id, token_network_identifier=payer_channel.token_network_identifier, channel_identifier=payer_channel.identifier, recipient=payer_channel.our_state.address, ) assert send_lock_expired lock_expired_message = message_from_sendevent(send_lock_expired, HOP1) lock_expired_message.sign(HOP2_KEY) balance_proof = balanceproof_from_envelope(lock_expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) expired_block_number = lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2 # Regression: The mediator must still be able to process the block which # expires the lock expire_block_iteration = mediator.state_transition( init_iteration.new_state, Block( block_number=expired_block_number, gas_limit=0, block_hash=None, ), channel_map, pseudo_random_generator, expired_block_number, ) assert expire_block_iteration.new_state is not None receive_expired_iteration = mediator.state_transition( expire_block_iteration.new_state, ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channel_map, pseudo_random_generator, expired_block_number, ) msg = 'The only used channel had the lock cleared, the task must be cleared' assert receive_expired_iteration.new_state is None, msg assert secrethash not in payer_channel.partner_state.secrethashes_to_lockedlocks
def test_regression_mediator_send_lock_expired_with_new_block(): """ The mediator must send the lock expired, but it must **not** clear itself if it has not **received** the corresponding message. """ amount = 10 block_number = 5 target = HOP2 expiration = 30 pseudo_random_generator = random.Random() payer_channel = factories.make_channel( partner_balance=amount, partner_address=UNIT_TRANSFER_SENDER, token_address=UNIT_TOKEN_ADDRESS, ) payer_route = factories.route_from_channel(payer_channel) payer_transfer = factories.make_signed_transfer_for( payer_channel, amount, HOP1, target, expiration, UNIT_SECRET, ) channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, ) available_routes = [factories.route_from_channel(channel1)] channel_map = { channel1.identifier: channel1, payer_channel.identifier: payer_channel, } init_state_change = ActionInitMediator( available_routes, payer_route, payer_transfer, ) initial_state = None init_iteration = mediator.state_transition( initial_state, init_state_change, channel_map, pseudo_random_generator, block_number, ) assert init_iteration.new_state is not None send_transfer = must_contain_entry(init_iteration.events, SendLockedTransfer, {}) assert send_transfer transfer = send_transfer.transfer block_expiration_number = transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2 block = Block( block_number=block_expiration_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = mediator.state_transition( init_iteration.new_state, block, channel_map, pseudo_random_generator, block_expiration_number, ) msg = ("The payer's lock has also expired, " "but it must not be removed locally (without an Expired lock)") assert transfer.lock.secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks, msg msg = 'The payer has not yet sent an expired lock, the task can not be cleared yet' assert iteration.new_state is not None, msg assert must_contain_entry(iteration.events, SendLockExpired, { 'secrethash': transfer.lock.secrethash, }) assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks
def test_channel_data_removed_after_unlock( chain_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, channel_state, open_block_number, ) channel_new_iteration = token_network.state_transition( payment_network_identifier, token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) 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_route = factories.route_from_channel(channel_state) init_target = ActionInitTarget( from_route, mediated_transfer, ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_state.address, channel_state.identifier, closed_block_number, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier, channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( factories.make_transaction_hash(), token_network_state.address, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( payment_network_identifier, channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) 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 unlock_blocknumber = settle_block_number + 5 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, ) channel_unlock_iteration = token_network.state_transition( payment_network_identifier, channel_settled_iteration.new_state, channel_batch_unlock_state_change, pseudo_random_generator, unlock_blocknumber, ) token_network_state_after_unlock = channel_unlock_iteration.new_state ids_to_channels = token_network_state_after_unlock.channelidentifiers_to_channels assert len(ids_to_channels) == 0
def test_initiator_lock_expired(): amount = UNIT_TRANSFER_AMOUNT * 2 channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), ] block_number = 10 transfer_description = factories.make_transfer_description( secret=UNIT_SECRET, payment_network_identifier=channel1.payment_network_identifier, ) current_state = make_initiator_manager_state( available_routes, transfer_description, channel_map, pseudo_random_generator, block_number, ) transfer = current_state.initiator.transfer assert transfer.lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks # Trigger lock expiry state_change = Block( block_number=transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert events.must_contain_entry( iteration.events, SendLockExpired, { 'balance_proof': { 'nonce': 2, 'transferred_amount': 0, 'locked_amount': 0, }, 'secrethash': transfer.lock.secrethash, 'recipient': channel1.partner_state.address, }) # Since the lock expired make sure we also get the payment sent failed event assert events.must_contain_entry( iteration.events, EventPaymentSentFailed, { 'payment_network_identifier': channel1.payment_network_identifier, 'token_network_identifier': channel1.token_network_identifier, 'identifier': UNIT_TRANSFER_IDENTIFIER, 'target': transfer.target, 'reason': "transfer's lock has expired", }) assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks msg = 'the initiator payment task must be deleted at block of the lock expiration' assert not iteration.new_state, msg # Create 2 other transfers transfer2_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer2'), channel_map, pseudo_random_generator, 30, ) transfer2_lock = transfer2_state.initiator.transfer.lock transfer3_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer3'), channel_map, pseudo_random_generator, 32, ) transfer3_lock = transfer3_state.initiator.transfer.lock assert len(channel1.our_state.secrethashes_to_lockedlocks) == 2 assert transfer2_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks expiration_block_number = transfer2_lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2 block = Block( block_number=expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( transfer2_state, block, channel_map, pseudo_random_generator, expiration_block_number, ) # Transfer 2 expired assert transfer2_lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Transfer 3 is still there assert transfer3_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks
def test_routing_priority( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 open_block_number_hash = factories.make_block_hash() pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() # 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.make_channel( our_balance=1, our_address=our_address, partner_balance=1, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=2, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, 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(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_number_hash, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=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( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address1 assert routes[1].node_address == address2 # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, address4: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address4, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2 assert routes[1].node_address == address1
def test_routing_issue2663( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_UNREACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2 == [] # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_UNREACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2
def test_initiator_lock_expired(): amount = UNIT_TRANSFER_AMOUNT * 2 channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), ] block_number = 10 transfer_description = factories.make_transfer_description( secret=UNIT_SECRET, payment_network_identifier=channel1.payment_network_identifier, ) current_state = make_initiator_manager_state( available_routes, transfer_description, channel_map, pseudo_random_generator, block_number, ) transfer = current_state.initiator.transfer assert transfer.lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks # Trigger lock expiry state_change = Block( block_number=channel.get_sender_expiration_threshold(transfer.lock), gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert events.must_contain_entry(iteration.events, SendLockExpired, { 'balance_proof': { 'nonce': 2, 'transferred_amount': 0, 'locked_amount': 0, }, 'secrethash': transfer.lock.secrethash, 'recipient': channel1.partner_state.address, }) # Since the lock expired make sure we also get the payment sent failed event assert events.must_contain_entry(iteration.events, EventPaymentSentFailed, { 'payment_network_identifier': channel1.payment_network_identifier, 'token_network_identifier': channel1.token_network_identifier, 'identifier': UNIT_TRANSFER_IDENTIFIER, 'target': transfer.target, 'reason': "transfer's lock has expired", }) assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks msg = 'the initiator payment task must be deleted at block of the lock expiration' assert not iteration.new_state, msg # Create 2 other transfers transfer2_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer2'), channel_map, pseudo_random_generator, 30, ) transfer2_lock = transfer2_state.initiator.transfer.lock transfer3_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer3'), channel_map, pseudo_random_generator, 32, ) transfer3_lock = transfer3_state.initiator.transfer.lock assert len(channel1.our_state.secrethashes_to_lockedlocks) == 2 assert transfer2_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks expiration_block_number = channel.get_sender_expiration_threshold(transfer2_lock) block = Block( block_number=expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( transfer2_state, block, channel_map, pseudo_random_generator, expiration_block_number, ) # Transfer 2 expired assert transfer2_lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Transfer 3 is still there assert transfer3_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks
def test_state_wait_secretrequest_invalid_amount_and_sender(): amount = UNIT_TRANSFER_AMOUNT block_number = 1 pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) lock = channel.get_lock( channel1.our_state, current_state.initiator.transfer_description.secrethash, ) state_change = ReceiveSecretRequest( UNIT_TRANSFER_IDENTIFIER, lock.amount + 1, lock.expiration, lock.secrethash, UNIT_TRANSFER_INITIATOR, ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert len(iteration.events) == 0 assert iteration.new_state.initiator.received_secret_request is False # Now the proper target sends the message, this should be applied state_change_2 = ReceiveSecretRequest( UNIT_TRANSFER_IDENTIFIER, lock.amount, lock.expiration, lock.secrethash, UNIT_TRANSFER_TARGET, ) iteration2 = initiator_manager.state_transition( iteration.new_state, state_change_2, channel_map, pseudo_random_generator, block_number, ) assert iteration2.new_state.initiator.received_secret_request is True assert isinstance(iteration2.events[0], SendSecretReveal)
def test_refund_transfer_no_more_routes(): amount = UNIT_TRANSFER_AMOUNT block_number = 1 refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=UNIT_TRANSFER_INITIATOR, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channelmap = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channelmap, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer channel_identifier = current_state.initiator.channel_identifier channel_state = channelmap[channel_identifier] refund_transfer = factories.make_signed_transfer( amount, original_transfer.initiator, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) state_change = ReceiveTransferRefundCancelRoute( sender=channel_state.partner_state.address, routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channelmap, pseudo_random_generator, block_number, ) assert iteration.new_state is None unlocked_failed = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) sent_failed = next(e for e in iteration.events if isinstance(e, EventPaymentSentFailed)) assert unlocked_failed assert sent_failed
def test_state_transition(): """ Happy case testing. """ lock_amount = 7 block_number = 1 initiator = factories.HOP6 payment_network_identifier = factories.make_address() pseudo_random_generator = random.Random() our_balance = 100 our_address = factories.make_address() partner_balance = 130 from_channel = factories.make_channel( our_address=our_address, our_balance=our_balance, partner_address=UNIT_TRANSFER_SENDER, partner_balance=partner_balance, ) from_route = factories.route_from_channel(from_channel) expiration = block_number + from_channel.settle_timeout from_transfer = factories.make_signed_transfer_for( from_channel, lock_amount, initiator, our_address, expiration, UNIT_SECRET, ) init = ActionInitTarget( payment_network_identifier, from_route, from_transfer, ) init_transition = target.state_transition( None, init, from_channel, pseudo_random_generator, block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == from_route assert init_transition.new_state.transfer == from_transfer first_new_block = Block(block_number + 1) first_block_iteration = target.state_transition( init_transition.new_state, first_new_block, from_channel, pseudo_random_generator, first_new_block.block_number, ) secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator) reveal_iteration = target.state_transition( first_block_iteration.new_state, secret_reveal, from_channel, pseudo_random_generator, first_new_block, ) assert reveal_iteration.events second_new_block = Block(block_number + 2) iteration = target.state_transition( init_transition.new_state, second_new_block, from_channel, pseudo_random_generator, second_new_block.block_number, ) assert not iteration.events nonce = from_transfer.balance_proof.nonce + 1 transferred_amount = lock_amount locksroot = EMPTY_MERKLE_ROOT invalid_message_hash = b'\x00' * 32 locked_amount = 0 balance_proof = factories.make_signed_balance_proof( nonce, transferred_amount, locked_amount, from_route.channel_identifier, locksroot, invalid_message_hash, UNIT_TRANSFER_PKEY, UNIT_TRANSFER_SENDER, ) payment_network_identifier = factories.make_address() balance_proof_state_change = ReceiveUnlock( random.randint(0, UINT64_MAX), UNIT_SECRET, balance_proof, ) proof_iteration = target.state_transition( init_transition.new_state, balance_proof_state_change, from_channel, pseudo_random_generator, block_number + 2, ) assert proof_iteration.new_state is None
def test_state_transition(): """ Happy case testing. """ lock_amount = 7 block_number = 1 initiator = factories.HOP6 pseudo_random_generator = random.Random() our_balance = 100 our_address = factories.make_address() partner_balance = 130 from_channel = factories.make_channel( our_address=our_address, our_balance=our_balance, partner_address=UNIT_TRANSFER_SENDER, partner_balance=partner_balance, ) from_route = factories.route_from_channel(from_channel) expiration = block_number + from_channel.settle_timeout from_transfer = factories.make_signed_transfer_for( from_channel, lock_amount, initiator, our_address, expiration, UNIT_SECRET, ) init = ActionInitTarget( from_route, from_transfer, ) init_transition = target.state_transition( None, init, from_channel, pseudo_random_generator, block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == from_route assert init_transition.new_state.transfer == from_transfer first_new_block = Block(block_number + 1) first_block_iteration = target.state_transition( init_transition.new_state, first_new_block, from_channel, pseudo_random_generator, first_new_block.block_number, ) secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator) reveal_iteration = target.state_transition( first_block_iteration.new_state, secret_reveal, from_channel, pseudo_random_generator, first_new_block, ) assert reveal_iteration.events second_new_block = Block(block_number + 2) iteration = target.state_transition( init_transition.new_state, second_new_block, from_channel, pseudo_random_generator, second_new_block.block_number, ) assert not iteration.events nonce = from_transfer.balance_proof.nonce + 1 transferred_amount = lock_amount locksroot = EMPTY_MERKLE_ROOT invalid_message_hash = b'\x00' * 32 locked_amount = 0 balance_proof = factories.make_signed_balance_proof( nonce, transferred_amount, locked_amount, from_channel.token_network_identifier, from_route.channel_identifier, locksroot, invalid_message_hash, UNIT_TRANSFER_PKEY, UNIT_TRANSFER_SENDER, ) balance_proof_state_change = ReceiveUnlock( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, balance_proof=balance_proof, ) proof_iteration = target.state_transition( init_transition.new_state, balance_proof_state_change, from_channel, pseudo_random_generator, block_number + 2, ) assert proof_iteration.new_state is None
def create_square_network_topology( payment_network_state, token_network_state, our_address, ) -> typing.Tuple[ TokenNetworkState, typing.List[typing.Address], typing.List[NettingChannelState], ]: open_block_number = 10 pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) 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 return ( channel_new_iteration4.new_state, [address1, address2, address3], (channel_state1, channel_state2), )
def test_mediator_clear_pairs_after_batch_unlock( chain_state, token_network_state, our_address, ): """ Regression test for https://github.com/raiden-network/raiden/issues/2932 The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where he is a participant is received. """ open_block_number = 10 pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, channel_state, open_block_number, ) channel_new_iteration = token_network.state_transition( payment_network_identifier, token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) 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_route = factories.route_from_channel(channel_state) init_mediator = ActionInitMediator( routes=[from_route], from_route=from_route, from_transfer=mediated_transfer, ) node.state_transition(chain_state, init_mediator) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_state.address, channel_state.identifier, closed_block_number, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier, channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( factories.make_transaction_hash(), token_network_state.address, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( payment_network_identifier, channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) 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 block_number = closed_block_number + 1 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=block_number, ) channel_unlock_iteration = node.state_transition( chain_state=chain_state, state_change=channel_batch_unlock_state_change, ) chain_state = channel_unlock_iteration.new_state token_network_state = views.get_token_network_by_identifier( chain_state=chain_state, token_network_id=token_network_state.address, ) ids_to_channels = token_network_state.channelidentifiers_to_channels assert len(ids_to_channels) == 0 # Make sure that all is fine in the next block block = Block( block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = node.state_transition( chain_state=chain_state, state_change=block, ) assert iteration.new_state # Make sure that mediator task was cleared during the next block processing # since the channel was removed mediator_task = chain_state.payment_mapping.secrethashes_to_task.get(lock_secrethash) assert not mediator_task
def test_mediator_clear_pairs_after_batch_unlock( chain_state, token_network_state, our_address, ): """ Regression test for https://github.com/raiden-network/raiden/issues/2932 The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where he is a participant is received. """ open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, block_hash=open_block_hash, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) 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_route = factories.route_from_channel(channel_state) init_mediator = ActionInitMediator( routes=[from_route], from_route=from_route, from_transfer=mediated_transfer, ) node.state_transition(chain_state, init_mediator) 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, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), ) channel_settled_iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, block_hash=closed_block_hash, ) 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 block_number = closed_block_number + 1 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=block_number, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = node.state_transition( chain_state=chain_state, state_change=channel_batch_unlock_state_change, ) chain_state = channel_unlock_iteration.new_state token_network_state = views.get_token_network_by_identifier( chain_state=chain_state, token_network_id=token_network_state.address, ) ids_to_channels = token_network_state.channelidentifiers_to_channels assert len(ids_to_channels) == 0 # Make sure that all is fine in the next block block = Block( block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = node.state_transition( chain_state=chain_state, state_change=block, ) assert iteration.new_state # Make sure that mediator task was cleared during the next block processing # since the channel was removed mediator_task = chain_state.payment_mapping.secrethashes_to_task.get( lock_secrethash) assert not mediator_task
def test_routing_updates( token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address1, ) payment_network_identifier = factories.make_payment_network_identifier() # create a new channel as participant, check graph update channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) graph_state = channel_new_iteration1.new_state.network_graph assert channel_state.identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 1 assert graph_state.network[our_address][address1] is not None assert len(graph_state.network.edges()) == 1 # create a new channel without being participant, check graph update new_channel_identifier = factories.make_channel_identifier() channel_new_state_change = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) graph_state = channel_new_iteration2.new_state.network_graph assert channel_state.identifier in graph_state.channel_identifier_to_participants assert new_channel_identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 2 assert graph_state.network[our_address][address1] is not None assert graph_state.network[address2][address3] is not None assert len(graph_state.network.edges()) == 2 # close the channel the node is a participant of, check edge is removed from graph closed_block_number = open_block_number + 20 channel_close_state_change1 = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, ) channel_closed_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_new_iteration2.new_state, state_change=channel_close_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, ) # Check that a second ContractReceiveChannelClosed events is handled properly # This might have been sent from the other participant of the channel # See issue #2449 channel_close_state_change2 = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.our_state.address, token_network_identifier=token_network_state.address, channel_identifier=channel_state.identifier, block_number=closed_block_number, ) channel_closed_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration1.new_state, state_change=channel_close_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number, ) graph_state = channel_closed_iteration2.new_state.network_graph assert channel_state.identifier not in graph_state.channel_identifier_to_participants assert new_channel_identifier in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 1 assert graph_state.network[address2][address3] is not None assert len(graph_state.network.edges()) == 1 # close the channel the node is not a participant of, check edge is removed from graph channel_close_state_change3 = ContractReceiveRouteClosed( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, block_number=closed_block_number, ) channel_closed_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration2.new_state, state_change=channel_close_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number + 10, ) # Check that a second ContractReceiveRouteClosed events is handled properly. # This might have been sent from the second participant of the channel # See issue #2449 channel_close_state_change4 = ContractReceiveRouteClosed( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=new_channel_identifier, block_number=closed_block_number + 10, ) channel_closed_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=channel_closed_iteration3.new_state, state_change=channel_close_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=closed_block_number + 10, ) graph_state = channel_closed_iteration4.new_state.network_graph assert channel_state.identifier not in graph_state.channel_identifier_to_participants assert new_channel_identifier not in graph_state.channel_identifier_to_participants assert len(graph_state.channel_identifier_to_participants) == 0 assert len(graph_state.network.edges()) == 0
def test_channel_settle_must_properly_cleanup(): open_block_number = 10 open_block_hash = factories.make_block_hash() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) amount = 30 our_balance = amount + 50 channel_state = factories.make_channel(our_balance=our_balance) 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, ) 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, ) 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=EMPTY_MERKLE_ROOT, partner_onchain_locksroot=EMPTY_MERKLE_ROOT, ) 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, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert channel_state.identifier not in ids_to_channels
def test_routing_priority( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() pkey4, address4 = factories.make_privkey_address() # 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.make_channel( our_balance=1, our_address=our_address, partner_balance=1, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=2, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address4, block_number=open_block_number, ) channel_new_iteration5 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address2, participant2=address4, block_number=open_block_number, ) token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address1 assert routes[1].node_address == address2 # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, address4: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address4, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2 assert routes[1].node_address == address1 # sufficient routing capacity overwrites refunding capacity chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=2, previous_address=None, config={}, ) assert routes[0].node_address == address2 # availability overwrites refunding capacity (node 1 offline) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2
def test_refund_transfer_next_route(): amount = UNIT_TRANSFER_AMOUNT our_address = factories.ADDR refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=our_address, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channelmap = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 current_state = make_initiator_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channelmap, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer channel_identifier = current_state.initiator.channel_identifier channel_state = channelmap[channel_identifier] refund_transfer = factories.make_signed_transfer( amount, our_address, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) assert channel_state.partner_state.address == refund_address state_change = ReceiveTransferRefundCancelRoute( sender=refund_address, routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channelmap, pseudo_random_generator, block_number, ) assert iteration.new_state is not None route_cancelled = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) new_transfer = next(e for e in iteration.events if isinstance(e, SendLockedTransfer)) assert route_cancelled, 'The previous transfer must be cancelled' assert new_transfer, 'No mediated transfer event emitted, should have tried a new route' msg = 'the new transfer must use a new secret / secrethash' assert new_transfer.transfer.lock.secrethash != refund_transfer.lock.secrethash, msg assert iteration.new_state.initiator is not None