def test_get_snapshot_closest_to_state_change(): wal = new_wal(state_transtion_acc) block1 = Block( block_number=5, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block1) wal.snapshot() block2 = Block( block_number=7, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block2) wal.snapshot() block3 = Block( block_number=8, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block3) wal.snapshot() _, snapshot = wal.storage.get_snapshot_closest_to_state_change('latest') assert snapshot.state_changes == [block1, block2, block3]
def test_restore_without_snapshot(): wal = new_wal(state_transition_noop) block1 = Block( block_number=5, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block1) block2 = Block( block_number=7, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block2) block3 = Block( block_number=8, gas_limit=1, block_hash=factories.make_transaction_hash(), ) wal.log_and_dispatch(block3) newwal = restore_to_state_change( transition_function=state_transtion_acc, storage=wal.storage, state_change_identifier='latest', ) aggregate = newwal.state_manager.current_state assert aggregate.state_changes == [block1, block2, block3]
def test_transfer_statechange_operators(): # pylint: disable=unneeded-not block_hash = factories.make_transaction_hash() a = Block( block_number=2, gas_limit=1, block_hash=block_hash, ) b = Block( block_number=2, gas_limit=1, block_hash=block_hash, ) c = Block( block_number=3, gas_limit=1, block_hash=factories.make_transaction_hash(), ) assert a == b assert not a != b assert a != c assert not a == c a = ActionCancelPayment(2) b = ActionCancelPayment(2) c = ActionCancelPayment(3) assert a == b assert not a != b assert a != c assert not a == c
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_initiator_handle_contract_receive_after_channel_closed(): """ Initiator must accept on-chain secret reveal if the channel is closed. However, the off-chain unlock must not be done! This will happen because secrets are registered after a channel is closed, during the settlement window. """ block_number = 10 setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=block_number) transfer = setup.current_state.initiator.transfer assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks channel_closed = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=factories.make_address(), token_network_identifier=setup.channel.token_network_identifier, channel_identifier=setup.channel.identifier, block_number=block_number, ) channel_close_transition = channel.state_transition( channel_state=setup.channel, state_change=channel_closed, pseudo_random_generator=setup.prng, block_number=block_number, ) channel_state = channel_close_transition.new_state state_change = ContractReceiveSecretReveal( transaction_hash=factories.make_transaction_hash(), secret_registry_address=factories.make_address(), secrethash=transfer.lock.secrethash, secret=UNIT_SECRET, block_number=transfer.lock.expiration, ) channel_map = { channel_state.identifier: channel_state, } iteration = initiator_manager.handle_onchain_secretreveal( payment_state=setup.current_state, state_change=state_change, channelidentifiers_to_channels=channel_map, pseudo_random_generator=setup.prng, ) secrethash = setup.current_state.initiator.transfer_description.secrethash assert secrethash in channel_state.our_state.secrethashes_to_onchain_unlockedlocks msg = 'The channel is closed already, the balance proof must not be sent off-chain' assert not events.must_contain_entry(iteration.events, SendBalanceProof, {}), msg
def test_handle_offchain_secretreveal_after_lock_expired(): """Test that getting the secret revealed after lock expiration for the target does not end up continuously emitting EventUnlockClaimFailed Target part for https://github.com/raiden-network/raiden/issues/3086 """ setup = make_target_state() lock_expiration_block_number = channel.get_sender_expiration_threshold( setup.new_state.transfer.lock, ) lock_expiration_block = Block( block_number=lock_expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=setup.new_state, state_change=lock_expiration_block, channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=lock_expiration_block_number, ) state = iteration.new_state msg = 'At the expiration block we should get an EventUnlockClaimFailed' assert must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg iteration = target.state_transition( target_state=state, state_change=ReceiveSecretReveal(UNIT_SECRET, setup.initiator), channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=lock_expiration_block_number + 1, ) state = iteration.new_state next_block = Block( block_number=lock_expiration_block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=state, state_change=next_block, channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=lock_expiration_block_number + 1, ) msg = 'At the next block we should not get the same event' assert not must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg
def test_lock_expiry_updates_balance_proof(): setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=10) transfer = setup.current_state.initiator.transfer assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks nonce_before_lock_expiry = setup.channel.our_state.balance_proof.nonce # Trigger lock expiry state_change = Block( block_number=channel.get_sender_expiration_threshold(transfer.lock), gas_limit=1, block_hash=factories.make_transaction_hash(), ) initiator_manager.state_transition( setup.current_state, state_change, setup.channel_map, setup.prng, setup.block_number, ) balance_proof = setup.channel.our_state.balance_proof assert balance_proof.nonce == nonce_before_lock_expiry + 1 assert balance_proof.transferred_amount == 0 assert balance_proof.locked_amount == 0
def test_initiator_handle_contract_receive_secret_reveal_expired(): """ Initiator must *not* unlock off-chain if the secret is revealed on-chain *after* the lock expiration. """ setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=10) transfer = setup.current_state.initiator.transfer assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks state_change = ContractReceiveSecretReveal( transaction_hash=factories.make_transaction_hash(), secret_registry_address=factories.make_address(), secrethash=transfer.lock.secrethash, secret=UNIT_SECRET, block_number=transfer.lock.expiration + 1, ) iteration = initiator_manager.handle_onchain_secretreveal( payment_state=setup.current_state, state_change=state_change, channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=setup.prng, ) assert events.must_contain_entry(iteration.events, SendBalanceProof, {}) is None
def test_initiator_handle_contract_receive_emptyhash_secret_reveal(): """ Initiator must not accept contract receive secret reveal with emptyhash """ setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=10) transfer = setup.current_state.initiator.transfer assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks state_change = ContractReceiveSecretReveal( transaction_hash=factories.make_transaction_hash(), secret_registry_address=factories.make_address(), secrethash=transfer.lock.secrethash, secret=EMPTY_HASH, block_number=transfer.lock.expiration, ) iteration = initiator_manager.handle_onchain_secretreveal( payment_state=setup.current_state, state_change=state_change, channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=setup.prng, ) assert len(iteration.events) == 0 # make sure the original lock wasn't moved assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks
def test_initiator_handle_contract_receive_secret_reveal(): """ Initiator must unlock off-chain if the secret is revealed on-chain and the channel is open. """ setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=10) transfer = setup.current_state.initiator.transfer assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks state_change = ContractReceiveSecretReveal( transaction_hash=factories.make_transaction_hash(), secret_registry_address=factories.make_address(), secrethash=transfer.lock.secrethash, secret=UNIT_SECRET, block_number=transfer.lock.expiration, ) message_identifier = message_identifier_from_prng(deepcopy(setup.prng)) iteration = initiator_manager.handle_onchain_secretreveal( payment_state=setup.current_state, state_change=state_change, channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=setup.prng, ) payment_identifier = setup.current_state.initiator.transfer_description.payment_identifier assert events.must_contain_entry(iteration.events, SendBalanceProof, { 'message_identifier': message_identifier, 'payment_identifier': payment_identifier, })
def settle_channel(self, partner): channel = self.address_to_channel[partner] channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), token_network_identifier=channel.token_network_identifier, channel_identifier=channel.identifier, block_number=self.block_number + 1, ) node.state_transition(self.chain_state, channel_settled_state_change)
def new_channel_with_transaction(self): partner_address = self.new_channel() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), self.token_network_id, self.address_to_channel[partner_address], self.block_number, ) node.state_transition(self.chain_state, channel_new_state_change) return partner_address
def test_initiator_lock_expired_must_not_be_sent_if_channel_is_closed(): """ If the channel is closed there is no rason to send balance proofs off-chain, so a remove expired lock must not be sent when the channel is closed. """ block_number = 10 setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=block_number) channel_closed = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=factories.make_address(), token_network_identifier=setup.channel.token_network_identifier, channel_identifier=setup.channel.identifier, block_number=block_number, ) channel_close_transition = channel.state_transition( channel_state=setup.channel, state_change=channel_closed, pseudo_random_generator=setup.prng, block_number=block_number, ) channel_state = channel_close_transition.new_state expiration_block_number = channel.get_sender_expiration_threshold(setup.lock) block = Block( block_number=expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) channel_map = {channel_state.identifier: channel_state} iteration = initiator_manager.state_transition( setup.current_state, block, channel_map, setup.prng, expiration_block_number, ) assert events.must_contain_entry(iteration.events, SendLockExpired, {}) is None
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. """ pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair() payer_transfer = factories.make_signed_transfer_for(channels[0], LONG_EXPIRATION) init_iteration = mediator.state_transition( mediator_state=None, state_change=factories.mediator_make_init_action(channels, payer_transfer), channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=5, ) 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 = channel.get_sender_expiration_threshold(transfer.lock) block = Block( block_number=block_expiration_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = mediator.state_transition( mediator_state=init_iteration.new_state, state_change=block, channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=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 channels[0].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 channels[1].our_state.secrethashes_to_lockedlocks
def test_handle_block_lower_block_number(): """ Nothing changes. """ setup = make_target_state(block_number=10) new_block = Block( block_number=setup.block_number - 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=setup.new_state, state_change=new_block, channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=new_block.block_number, ) assert iteration.new_state assert not iteration.events
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_refund_transfer_no_more_routes(): amount = UNIT_TRANSFER_AMOUNT refund_pkey, refund_address = factories.make_privkey_address() setup = setup_initiator_tests( amount=amount, partner_balance=amount, our_address=UNIT_TRANSFER_INITIATOR, partner_address=refund_address, ) original_transfer = setup.current_state.initiator.transfer 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=setup.channel.identifier, pkey=refund_pkey, sender=refund_address, ) state_change = ReceiveTransferRefundCancelRoute( routes=setup.available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( setup.current_state, state_change, setup.channel_map, setup.prng, setup.block_number, ) current_state = iteration.new_state # As per the description of the issue here: # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046 # We can fail the payment but can't delete the payment task if there are no # more routes, but we have to wait for the lock expiration assert iteration.new_state is not 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 invalid_balance_proof = factories.make_signed_balance_proof( nonce=2, transferred_amount=original_transfer.balance_proof.transferred_amount, locked_amount=0, token_network_address=original_transfer.balance_proof.token_network_identifier, channel_identifier=setup.channel.identifier, locksroot=EMPTY_MERKLE_ROOT, extra_hash=original_transfer.lock.secrethash, sender_address=refund_address, ) balance_proof = factories.make_signed_balance_proof( nonce=2, transferred_amount=original_transfer.balance_proof.transferred_amount, locked_amount=0, token_network_address=original_transfer.balance_proof.token_network_identifier, channel_identifier=setup.channel.identifier, locksroot=EMPTY_MERKLE_ROOT, extra_hash=original_transfer.lock.secrethash, sender_address=refund_address, private_key=refund_pkey, ) invalid_lock_expired_state_change = ReceiveLockExpired( invalid_balance_proof, secrethash=original_transfer.lock.secrethash, message_identifier=5, ) lock_expired_state_change = ReceiveLockExpired( balance_proof, secrethash=original_transfer.lock.secrethash, message_identifier=5, ) before_expiry_block = original_transfer.lock.expiration - 1 expiry_block = channel.get_sender_expiration_threshold(original_transfer.lock) # a block before lock expiration, no events should be emitted current_state = iteration.new_state state_change = Block( block_number=before_expiry_block, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block, ) assert not iteration.events assert iteration.new_state, 'payment task should not be deleted at this block' # process an invalid lock expired message before lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, invalid_lock_expired_state_change, setup.channel_map, setup.prng, before_expiry_block, ) assert iteration.new_state, 'payment task should not be deleted at this lock expired' # should not be accepted assert not events.must_contain_entry(iteration.events, SendProcessed, {}) assert events.must_contain_entry(iteration.events, EventInvalidReceivedLockExpired, {}) # process a valid lock expired message before lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, lock_expired_state_change, setup.channel_map, setup.prng, before_expiry_block, ) assert iteration.new_state, 'payment task should not be deleted at this lock expired' # should not be accepted assert not events.must_contain_entry(iteration.events, SendProcessed, {}) # now we get to the lock expiration block current_state = iteration.new_state state_change = Block( block_number=expiry_block, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block, ) assert events.must_contain_entry(iteration.events, SendLockExpired, {}) # Since there was a refund transfer the payment task must not have been deleted assert iteration.new_state is not None # process the lock expired message after lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, lock_expired_state_change, setup.channel_map, setup.prng, expiry_block, ) # should be accepted assert events.must_contain_entry(iteration.events, SendProcessed, {}) assert iteration.new_state, 'payment task should be there waiting for next block' # process the the block after lock expiration current_state = iteration.new_state state_change = Block( block_number=expiry_block + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block + 1, ) assert iteration.new_state is None, 'from this point on the payment task should go'
def test_routing_updates(token_network_state, our_address, channel_properties): open_block_number = 10 properties, _ = channel_properties address1 = properties.partner_state.address address2 = factories.make_address() address3 = factories.make_address() pseudo_random_generator = random.Random() channel_state = factories.create(properties) 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(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) 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(), canonical_identifier=factories.make_canonical_identifier( token_network_address=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( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) 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, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration1 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_close_state_change1, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) # 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, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration2 = token_network.state_transition( token_network_state=channel_closed_iteration1.new_state, state_change=channel_close_state_change2, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) 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(), canonical_identifier=factories.make_canonical_identifier( token_network_address=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( token_network_state=channel_closed_iteration2.new_state, state_change=channel_close_state_change3, block_number=closed_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) # 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(), canonical_identifier=factories.make_canonical_identifier( token_network_address=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( token_network_state=channel_closed_iteration3.new_state, state_change=channel_close_state_change4, block_number=closed_block_number + 10, block_hash=closed_block_plus_10_hash, pseudo_random_generator=pseudo_random_generator, ) 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_routing_priority(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = factories.make_block_number() open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 1/1 ----> (1) # | | # | | # 2/0 x # | | # v v # (2) ----- x -----> (3) # | | # | | # x x # | | # v v # (4) (4) channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=1, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=1, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=2, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address2, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) token_network.state_transition( token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, } routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, privkey=b"", ) assert routes[0].next_hop_address == address1 assert routes[1].next_hop_address == address2 # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=1, previous_address=None, config={}, privkey=b"", ) assert routes[0].next_hop_address == address2 assert routes[1].next_hop_address == address1
def test_internal_routing_mediation_fees(chain_state, token_network_state, one_to_n_address, our_address): """ Checks that requesting a route for a single-hop transfer will return the route with estimated_fee of zero. """ open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() pseudo_random_generator = random.Random() direct_channel_state = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) # create new channels as participant direct_channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=direct_channel_state, block_number=open_block_number, block_hash=open_block_number_hash, ) direct_channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=direct_channel_new_state_change, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) route_new_state_change = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address1, participant2=address2, block_number=open_block_number, block_hash=open_block_number_hash, ) route_new_iteration = token_network.state_transition( token_network_state=direct_channel_new_iteration.new_state, state_change=route_new_state_change, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = route_new_iteration.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, } # Routing to our direct partner would require 0 mediation fees.x routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, privkey=b"", # not used if pfs is not configured ) assert routes[0].estimated_fee == 0 # Routing to our address2 through address1 would charge 2% routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address2, amount=50, previous_address=None, config={}, privkey=b"", # not used if pfs is not configured ) assert routes[0].estimated_fee == round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * 50)
def test_mediator_clear_pairs_after_batch_unlock(chain_state, token_network_state, our_address, channel_properties): """ 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() properties, pkey = channel_properties address = properties.partner_state.address channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) route_state = RouteState( route=[ channel_state.our_state.address, channel_state.partner_state.address ], forward_channel_id=channel_state.canonical_identifier. channel_identifier, ) from_hop = factories.make_hop_from_channel(channel_state) init_mediator = ActionInitMediator( route_states=[route_state], from_hop=from_hop, from_transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_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, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels block_number = closed_block_number + 1 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=address, sender=our_address, locksroot=compute_locksroot(PendingLocksState([bytes(lock.encoded)])), 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_address( chain_state=chain_state, token_network_address=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_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 unlocked on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ block_number = 5 pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair() payer_transfer = factories.make_signed_transfer_for( channels[0], LONG_EXPIRATION) initial_iteration = mediator.state_transition( mediator_state=None, state_change=factories.mediator_make_init_action( channels, payer_transfer), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=factories.make_block_hash(), ) send_transfer = search_for_item(initial_iteration.events, SendLockedTransfer, {}) 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 - channels[1].reveal_timeout): block_state_change = Block( block_number=block_number, gas_limit=1, block_hash=factories.make_transaction_hash()) block_iteration = mediator.handle_block(new_state, block_state_change, channels.channel_map, pseudo_random_generator) 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( secret=UNIT_SECRET, sender=channels[1].partner_state.address) paid_iteration = mediator.state_transition( mediator_state=new_state, state_change=receive_secret, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=factories.make_block_hash(), ) 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( block_number=expired_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) block_iteration = mediator.handle_block( mediator_state=paid_state, state_change=expired_block_state_change, channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, )
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 unlocked on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ 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, ) channel_map = { channel1.identifier: channel1, payer_channel.identifier: payer_channel, } possible_routes = [factories.route_from_channel(channel1)] init_state_change = ActionInitMediator( possible_routes, payer_route, payer_transfer, ) initial_state = None initial_iteration = mediator.state_transition( initial_state, init_state_change, channel_map, pseudo_random_generator, block_number, ) send_transfer = must_contain_entry(initial_iteration.events, SendLockedTransfer, {}) 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 - channel1.reveal_timeout): block_state_change = Block( block_number=block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) block_iteration = mediator.handle_block( new_state, block_state_change, channel_map, pseudo_random_generator, ) 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, channel_map, pseudo_random_generator, 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( block_number=expired_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) block_iteration = mediator.handle_block( paid_state, expired_block_state_change, channel_map, pseudo_random_generator, )
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_regression_mediator_not_update_payer_state_twice(): """ Regression Test for https://github.com/raiden-network/raiden/issues/3086 Make sure that after a lock expired the mediator doesn't update the pair twice causing EventUnlockClaimFailed to be generated at every block. """ pseudo_random_generator = random.Random() pair = factories.mediator_make_channel_pair() payer_channel, payee_channel = pair.channels payer_route = factories.make_hop_from_channel(payer_channel) payer_transfer = factories.make_signed_transfer_for( payer_channel, LONG_EXPIRATION) init_state_change = ActionInitMediator( from_hop=payer_route, route_states=pair.get_routes(), from_transfer=payer_transfer, balance_proof=payer_transfer.balance_proof, sender=payer_transfer.balance_proof.sender, # pylint: disable=no-member ) iteration = mediator.state_transition( mediator_state=None, state_change=init_state_change, channelidentifiers_to_channels=pair.channel_map, nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=5, block_hash=factories.make_block_hash(), ) assert iteration.new_state is not None current_state = iteration.new_state send_transfer = search_for_item(iteration.events, SendLockedTransfer, {}) assert send_transfer transfer = send_transfer.transfer block_expiration_number = channel.get_sender_expiration_threshold( transfer.lock.expiration) block = Block(block_number=block_expiration_number, gas_limit=1, block_hash=factories.make_block_hash()) iteration = mediator.state_transition( mediator_state=current_state, state_change=block, channelidentifiers_to_channels=pair.channel_map, nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=block_expiration_number, block_hash=factories.make_block_hash(), ) msg = "At the expiration block we should get an EventUnlockClaimFailed" assert search_for_item(iteration.events, EventUnlockClaimFailed, {}), msg current_state = iteration.new_state next_block = Block( block_number=block_expiration_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) # Initiator receives the secret reveal after the lock expired receive_secret = ReceiveSecretReveal( secret=UNIT_SECRET, sender=payee_channel.partner_state.address) iteration = mediator.state_transition( mediator_state=current_state, state_change=receive_secret, channelidentifiers_to_channels=pair.channel_map, nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=next_block.block_number, block_hash=next_block.block_hash, ) current_state = iteration.new_state lock = payer_transfer.lock secrethash = lock.secrethash assert secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks assert current_state.transfers_pair[0].payee_state == "payee_expired" assert not channel.is_secret_known(payer_channel.partner_state, secrethash) assert mediator.is_safe_to_wait( lock_expiration=lock.expiration, reveal_timeout=payer_channel.reveal_timeout, block_number=lock.expiration + 10, ).fail iteration = mediator.state_transition( mediator_state=current_state, state_change=next_block, channelidentifiers_to_channels=pair.channel_map, nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=block_expiration_number, block_hash=factories.make_block_hash(), ) msg = "At the next block we should not get the same event" assert not search_for_item(iteration.events, EventUnlockClaimFailed, {}), msg
def test_refund_transfer_no_more_routes(): amount = UNIT_TRANSFER_AMOUNT refund_pkey, refund_address = factories.make_privkey_address() setup = setup_initiator_tests( amount=amount, partner_balance=amount, our_address=UNIT_TRANSFER_INITIATOR, partner_address=refund_address, ) original_transfer = setup.current_state.initiator.transfer 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=setup.channel.identifier, pkey=refund_pkey, sender=refund_address, ) state_change = ReceiveTransferRefundCancelRoute( routes=setup.available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( setup.current_state, state_change, setup.channel_map, setup.prng, setup.block_number, ) current_state = iteration.new_state # As per the description of the issue here: # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046 # We can fail the payment but can't delete the payment task if there are no # more routes, but we have to wait for the lock expiration assert iteration.new_state is not 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 invalid_balance_proof = factories.make_signed_balance_proof( nonce=2, transferred_amount=original_transfer.balance_proof.transferred_amount, locked_amount=0, token_network_address=original_transfer.balance_proof. token_network_identifier, channel_identifier=setup.channel.identifier, locksroot=EMPTY_MERKLE_ROOT, extra_hash=original_transfer.lock.secrethash, sender_address=refund_address, ) balance_proof = factories.make_signed_balance_proof( nonce=2, transferred_amount=original_transfer.balance_proof.transferred_amount, locked_amount=0, token_network_address=original_transfer.balance_proof. token_network_identifier, channel_identifier=setup.channel.identifier, locksroot=EMPTY_MERKLE_ROOT, extra_hash=original_transfer.lock.secrethash, sender_address=refund_address, private_key=refund_pkey, ) invalid_lock_expired_state_change = ReceiveLockExpired( invalid_balance_proof, secrethash=original_transfer.lock.secrethash, message_identifier=5, ) lock_expired_state_change = ReceiveLockExpired( balance_proof, secrethash=original_transfer.lock.secrethash, message_identifier=5, ) before_expiry_block = original_transfer.lock.expiration - 1 expiry_block = original_transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2 # a block before lock expiration, no events should be emitted current_state = iteration.new_state state_change = Block( block_number=before_expiry_block, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block, ) assert not iteration.events assert iteration.new_state, 'payment task should not be deleted at this block' # process an invalid lock expired message before lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, invalid_lock_expired_state_change, setup.channel_map, setup.prng, before_expiry_block, ) assert iteration.new_state, 'payment task should not be deleted at this lock expired' # should not be accepted assert not events.must_contain_entry(iteration.events, SendProcessed, {}) assert events.must_contain_entry(iteration.events, EventInvalidReceivedLockExpired, {}) # process a valid lock expired message before lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, lock_expired_state_change, setup.channel_map, setup.prng, before_expiry_block, ) assert iteration.new_state, 'payment task should not be deleted at this lock expired' # should not be accepted assert not events.must_contain_entry(iteration.events, SendProcessed, {}) # now we get to the lock expiration block current_state = iteration.new_state state_change = Block( block_number=expiry_block, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block, ) assert events.must_contain_entry(iteration.events, SendLockExpired, {}) # Since there was a refund transfer the payment task must not have been deleted assert iteration.new_state is not None # process the lock expired message after lock expiration current_state = iteration.new_state iteration = initiator_manager.state_transition( current_state, lock_expired_state_change, setup.channel_map, setup.prng, expiry_block, ) # should be accepted assert events.must_contain_entry(iteration.events, SendProcessed, {}) assert iteration.new_state, 'payment task should be there waiting for next block' # process the the block after lock expiration current_state = iteration.new_state state_change = Block( block_number=expiry_block + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, setup.channel_map, setup.prng, expiry_block + 1, ) assert iteration.new_state is None, 'from this point on the payment task should go'
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_write_read_log(): wal = new_wal(state_transition_noop) block_number = 1337 block_hash = factories.make_transaction_hash() block = Block( block_number=block_number, gas_limit=1, block_hash=block_hash, ) unlocked_amount = 10 returned_amount = 5 participant = factories.make_address() partner = factories.make_address() locksroot = sha3(b'test_write_read_log') contract_receive_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=factories.make_address(), ), participant=participant, partner=partner, locksroot=locksroot, unlocked_amount=unlocked_amount, returned_tokens=returned_amount, block_number=block_number, block_hash=block_hash, ) state_changes1 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count1 = len(state_changes1) wal.log_and_dispatch(block) state_changes2 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count2 = len(state_changes2) assert count1 + 1 == count2 wal.log_and_dispatch(contract_receive_unlock) state_changes3 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count3 = len(state_changes3) assert count2 + 1 == count3 result1, result2 = state_changes3[-2:] assert isinstance(result1, Block) assert result1.block_number == block_number assert isinstance(result2, ContractReceiveChannelBatchUnlock) assert result2.participant == participant assert result2.partner == partner assert result2.locksroot == locksroot assert result2.unlocked_amount == unlocked_amount assert result2.returned_tokens == returned_amount # Make sure state snapshot can only go for corresponding state change ids with pytest.raises(sqlite3.IntegrityError): wal.storage.write_state_snapshot(34, 'AAAA') # Make sure we can only have a single state snapshot assert wal.storage.get_latest_state_snapshot() is None wal.storage.write_state_snapshot(1, 'AAAA') assert wal.storage.get_latest_state_snapshot() == (1, 'AAAA') wal.storage.write_state_snapshot(2, 'BBBB') assert wal.storage.get_latest_state_snapshot() == (2, 'BBBB')
def test_regression_mediator_not_update_payer_state_twice(): """ Regression Test for https://github.com/raiden-network/raiden/issues/3086 Make sure that after a lock expired the mediator doesn't update the pair twice causing EventUnlockClaimFailed to be generated at every block. """ pseudo_random_generator = random.Random() pair = factories.mediator_make_channel_pair() payer_channel, payee_channel = pair.channels payer_route = factories.route_from_channel(payer_channel) payer_transfer = factories.make_signed_transfer_for(payer_channel, LONG_EXPIRATION) available_routes = [factories.route_from_channel(payee_channel)] init_state_change = ActionInitMediator( routes=available_routes, from_route=payer_route, from_transfer=payer_transfer, ) iteration = mediator.state_transition( mediator_state=None, state_change=init_state_change, channelidentifiers_to_channels=pair.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=5, ) assert iteration.new_state is not None current_state = iteration.new_state send_transfer = must_contain_entry(iteration.events, SendLockedTransfer, {}) assert send_transfer transfer = send_transfer.transfer block_expiration_number = channel.get_sender_expiration_threshold(transfer.lock) block = Block( block_number=block_expiration_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = mediator.state_transition( mediator_state=current_state, state_change=block, channelidentifiers_to_channels=pair.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=block_expiration_number, ) msg = 'At the expiration block we should get an EventUnlockClaimFailed' assert must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg current_state = iteration.new_state next_block = Block( block_number=block_expiration_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) # Initiator receives the secret reveal after the lock expired receive_secret = ReceiveSecretReveal( secret=UNIT_SECRET, sender=payee_channel.partner_state.address, ) iteration = mediator.state_transition( mediator_state=current_state, state_change=receive_secret, channelidentifiers_to_channels=pair.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=next_block.block_number, ) current_state = iteration.new_state lock = payer_transfer.lock secrethash = lock.secrethash assert secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks assert current_state.transfers_pair[0].payee_state == 'payee_expired' assert not channel.is_secret_known(payer_channel.partner_state, secrethash) safe_to_wait, _ = mediator.is_safe_to_wait( lock_expiration=lock.expiration, reveal_timeout=payer_channel.reveal_timeout, block_number=lock.expiration + 10, ) assert not safe_to_wait iteration = mediator.state_transition( mediator_state=current_state, state_change=next_block, channelidentifiers_to_channels=pair.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=block_expiration_number, ) msg = 'At the next block we should not get the same event' assert not must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg
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 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_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 test_channel_settle_must_properly_cleanup(channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() token_network_address = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState( address=token_network_address, token_address=token_id, network_graph=TokenNetworkGraphState(token_network_address), ) properties, _ = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert channel_state.identifier not in ids_to_channels
def test_routing_issue2663( chain_state, payment_network_state, 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() # 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 == 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_channel_data_removed_after_unlock(chain_state, token_network_state, our_address, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties address = properties.partner_state.address channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member balance_proof=mediated_transfer.balance_proof, from_hop=from_hop, transfer=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, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) channel_state_after_closed = channel_closed_iteration.new_state.channelidentifiers_to_channels[ channel_state.identifier] 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=compute_locksroot( channel_state_after_closed.our_state.pending_locks), partner_onchain_locksroot=compute_locksroot( channel_state_after_closed.partner_state.pending_locks), ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels unlock_blocknumber = settle_block_number + 5 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=our_address, sender=address, locksroot=compute_locksroot(PendingLocksState([bytes(lock.encoded)])), unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = token_network.state_transition( token_network_state=channel_settled_iteration.new_state, state_change=channel_batch_unlock_state_change, block_number=unlock_blocknumber, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) 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_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_multiple_channel_states(chain_state, token_network_state, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( from_hop=from_hop, transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels # Create new channel while the previous one is pending unlock new_channel_properties = factories.create_properties( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier()), defaults=properties, ) new_channel_state = factories.create(new_channel_properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=new_channel_state, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_new_open = channel_new_iteration.new_state ids_to_channels = token_network_state_after_new_open.channelidentifiers_to_channels assert len(ids_to_channels) == 2 assert channel_state.identifier in ids_to_channels
def test_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_routing_issue2663(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 50 ----> (1) <------50------ # | | # | | # 100 (4) # | ^ # v | # (2) ----- 100 ---> (3) <-------100--- channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=100, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration2.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration3.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 3 assert len(graph_state.network.edges()) == 3 channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration4.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 4 assert len(graph_state.network.edges()) == 4 channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=5), participant1=address1, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration5.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 5 assert len(graph_state.network.edges()) == 5 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, config={}, privkey=b"", # not used if pfs is not configured ) assert routes1[0].next_hop_address == address1 assert routes1[1].next_hop_address == address2 # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.UNREACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, config={}, privkey=b"", ) assert routes1[0].next_hop_address == address1 # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.UNREACHABLE, address4: NetworkState.REACHABLE, } routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, config={}, privkey=b"", ) assert routes1[0].next_hop_address == address1 assert routes1[1].next_hop_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.UNREACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=50, previous_address=None, config={}, privkey=b"", ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].next_hop_address == address2
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) 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( factories.make_transaction_hash(), token_network_id, 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, ) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_id, 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_id, 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 channel_state.identifier not in ids_to_channels
def test_channel_cleared_after_two_unlocks(): our_model, _ = create_model(balance=700, num_pending_locks=1) partner_model, partner_key1 = create_model(balance=700, num_pending_locks=1) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() pseudo_random_generator = random.Random() def make_unlock(unlock_end, partner_end): batch_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=partner_end.address, sender=unlock_end.address, locksroot=unlock_end.balance_proof.locksroot, unlocked_amount=10, returned_tokens=0, block_number=block_number, block_hash=block_hash, ) return batch_unlock settle_channel = ContractReceiveChannelSettled( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=compute_locksroot(channel_state.our_state.pending_locks), partner_onchain_locksroot=compute_locksroot(channel_state.partner_state.pending_locks), block_number=1, block_hash=make_block_hash(), ) iteration = channel.state_transition( channel_state=channel_state, state_change=settle_channel, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "both participants have pending locks, locksroot must not represent the empty list" assert iteration.new_state.our_state.onchain_locksroot != LOCKSROOT_OF_NO_LOCKS, msg assert iteration.new_state.partner_state.onchain_locksroot != LOCKSROOT_OF_NO_LOCKS, msg batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state) iteration = channel.state_transition( channel_state=iteration.new_state, state_change=batch_unlock, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "all of our locks has been unlocked, onchain state must be updated" assert iteration.new_state.our_state.onchain_locksroot is LOCKSROOT_OF_NO_LOCKS, msg msg = "partner has pending locks, the locksroot must not represent the empty list" assert iteration.new_state.partner_state.onchain_locksroot is not LOCKSROOT_OF_NO_LOCKS, msg msg = "partner locksroot is not unlocked, channel should not have been cleaned" assert iteration.new_state is not None, msg # processing the same unlock twice must not count iteration = channel.state_transition( channel_state=iteration.new_state, state_change=batch_unlock, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "partner has pending locks, the locksroot must not represent the empty list" assert iteration.new_state.partner_state.onchain_locksroot is not LOCKSROOT_OF_NO_LOCKS, msg msg = "partner locksroot is not unlocked, channel should not have been cleaned" assert iteration.new_state is not None, msg iteration = channel.state_transition( channel_state=iteration.new_state, state_change=make_unlock(channel_state.partner_state, channel_state.our_state), block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "all unlocks have been done, channel must be cleared" assert iteration.new_state is None, msg
def test_handle_offchain_secretreveal_after_lock_expired(): """Test that getting the secret revealed after lock expiration for the target does not end up continuously emitting EventUnlockClaimFailed Target part for https://github.com/raiden-network/raiden/issues/3086 """ amount = 3 block_number = 1 expiration = block_number + factories.UNIT_REVEAL_TIMEOUT initiator = factories.HOP1 our_address = factories.ADDR secret = factories.UNIT_SECRET pseudo_random_generator = random.Random() channel_state, state = make_target_state( our_address, amount, block_number, initiator, expiration, ) lock_expiration = state.transfer.lock.expiration lock_expiration_block_number = lock_expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2 lock_expiration_block = Block( block_number=lock_expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=state, state_change=lock_expiration_block, channel_state=channel_state, pseudo_random_generator=pseudo_random_generator, block_number=lock_expiration_block_number, ) state = iteration.new_state msg = 'At the expiration block we should get an EventUnlockClaimFailed' assert must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg iteration = target.state_transition( target_state=state, state_change=ReceiveSecretReveal(secret, initiator), channel_state=channel_state, pseudo_random_generator=pseudo_random_generator, block_number=lock_expiration_block_number + 1, ) state = iteration.new_state next_block = Block( block_number=lock_expiration_block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=state, state_change=next_block, channel_state=channel_state, pseudo_random_generator=pseudo_random_generator, block_number=lock_expiration_block_number + 1, ) msg = 'At the next block we should not get the same event' assert not must_contain_entry(iteration.events, EventUnlockClaimFailed, {}), msg
def test_write_read_log(): wal = new_wal(state_transition_noop) block_number = 1337 block = Block( block_number=block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) unlocked_amount = 10 returned_amount = 5 participant = factories.make_address() partner = factories.make_address() locksroot = sha3(b'test_write_read_log') contract_receive_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), token_network_identifier=factories.make_address(), participant=participant, partner=partner, locksroot=locksroot, unlocked_amount=unlocked_amount, returned_tokens=returned_amount, block_number=block_number, ) state_changes1 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count1 = len(state_changes1) wal.log_and_dispatch(block) state_changes2 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count2 = len(state_changes2) assert count1 + 1 == count2 wal.log_and_dispatch(contract_receive_unlock) state_changes3 = wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) count3 = len(state_changes3) assert count2 + 1 == count3 result1, result2 = state_changes3[-2:] assert isinstance(result1, Block) assert result1.block_number == block_number assert isinstance(result2, ContractReceiveChannelBatchUnlock) assert result2.participant == participant assert result2.partner == partner assert result2.locksroot == locksroot assert result2.unlocked_amount == unlocked_amount assert result2.returned_tokens == returned_amount # Make sure state snapshot can only go for corresponding state change ids with pytest.raises(sqlite3.IntegrityError): wal.storage.write_state_snapshot(34, 'AAAA') # Make sure we can only have a single state snapshot assert wal.storage.get_latest_state_snapshot() is None wal.storage.write_state_snapshot(1, 'AAAA') assert wal.storage.get_latest_state_snapshot() == (1, 'AAAA') wal.storage.write_state_snapshot(2, 'BBBB') assert wal.storage.get_latest_state_snapshot() == (2, 'BBBB')
def test_state_transition(): """ Happy case testing. """ lock_amount = 7 block_number = 1 initiator = factories.HOP6 pseudo_random_generator = random.Random() channels = make_channel_set([channel_properties2]) from_transfer = make_target_transfer(channels[0], amount=lock_amount, initiator=initiator) init = ActionInitTarget(channels.get_route(0), from_transfer) init_transition = target.state_transition( target_state=None, state_change=init, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == channels.get_route(0) assert init_transition.new_state.transfer == from_transfer first_new_block = Block( block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) first_block_iteration = target.state_transition( target_state=init_transition.new_state, state_change=first_new_block, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=first_new_block.block_number, ) secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator) reveal_iteration = target.state_transition( target_state=first_block_iteration.new_state, state_change=secret_reveal, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=first_new_block.block_number, ) assert reveal_iteration.events second_new_block = Block( block_number=block_number + 2, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = target.state_transition( target_state=init_transition.new_state, state_change=second_new_block, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=second_new_block.block_number, ) assert not iteration.events balance_proof = create(BalanceProofSignedStateProperties( balance_proof=BalanceProofProperties( nonce=from_transfer.balance_proof.nonce + 1, transferred_amount=lock_amount, locked_amount=0, token_network_identifier=channels[0].token_network_identifier, channel_identifier=channels.get_route(0).channel_identifier, locksroot=EMPTY_MERKLE_ROOT, ), message_hash=b'\x00' * 32, # invalid )) balance_proof_state_change = ReceiveUnlock( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, balance_proof=balance_proof, ) proof_iteration = target.state_transition( target_state=init_transition.new_state, state_change=balance_proof_state_change, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=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_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_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 unlocked on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ block_number = 5 pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair() payer_transfer = factories.make_signed_transfer_for(channels[0], LONG_EXPIRATION) initial_iteration = mediator.state_transition( mediator_state=None, state_change=factories.mediator_make_init_action(channels, payer_transfer), channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) send_transfer = must_contain_entry(initial_iteration.events, SendLockedTransfer, {}) 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 - channels[1].reveal_timeout): block_state_change = Block( block_number=block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) block_iteration = mediator.handle_block( new_state, block_state_change, channels.channel_map, pseudo_random_generator, ) 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, channels[1].partner_state.address, ) paid_iteration = mediator.state_transition( mediator_state=new_state, state_change=receive_secret, channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=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( block_number=expired_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) block_iteration = mediator.handle_block( mediator_state=paid_state, state_change=expired_block_state_change, channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, )
def test_state_transition(): """ Happy case testing. """ lock_amount = 7 block_number = 1 initiator = factories.make_address() pseudo_random_generator = random.Random() channels = make_channel_set([channel_properties2]) from_transfer = make_target_transfer(channels[0], amount=lock_amount, initiator=initiator) init = ActionInitTarget( from_hop=channels.get_hop(0), transfer=from_transfer, balance_proof=from_transfer.balance_proof, sender=from_transfer.balance_proof.sender, # pylint: disable=no-member ) init_transition = target.state_transition( target_state=None, state_change=init, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.from_hop == channels.get_hop(0) assert init_transition.new_state.transfer == from_transfer first_new_block = Block(block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash()) first_block_iteration = target.state_transition( target_state=init_transition.new_state, state_change=first_new_block, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=first_new_block.block_number, ) secret_reveal = ReceiveSecretReveal(secret=UNIT_SECRET, sender=initiator) reveal_iteration = target.state_transition( target_state=first_block_iteration.new_state, state_change=secret_reveal, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=first_new_block.block_number, ) assert reveal_iteration.events second_new_block = Block(block_number=block_number + 2, gas_limit=1, block_hash=factories.make_transaction_hash()) iteration = target.state_transition( target_state=init_transition.new_state, state_change=second_new_block, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=second_new_block.block_number, ) assert not iteration.events balance_proof = create( BalanceProofSignedStateProperties( nonce=from_transfer.balance_proof.nonce + 1, # pylint: disable=no-member transferred_amount=lock_amount, locked_amount=0, canonical_identifier=factories.make_canonical_identifier( token_network_address=channels[0].token_network_address, channel_identifier=channels.get_hop(0).channel_identifier, ), locksroot=LOCKSROOT_OF_NO_LOCKS, message_hash=b"\x00" * 32, # invalid )) balance_proof_state_change = ReceiveUnlock( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, balance_proof=balance_proof, sender=balance_proof.sender, # pylint: disable=no-member ) proof_iteration = target.state_transition( target_state=init_transition.new_state, state_change=balance_proof_state_change, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=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_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 first_new_block = Block( block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash(), ) 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=block_number + 2, gas_limit=1, block_hash=factories.make_transaction_hash(), ) 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 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_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) 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( factories.make_transaction_hash(), token_network_id, 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, ) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_id, 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_id, 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 channel_state.identifier not in ids_to_channels
def test_channel_data_removed_after_unlock( chain_state, token_network_state, our_address, ): open_block_number = 10 open_block_hash = factories.make_block_hash() 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, ) 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, ) 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, 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=factories.make_32bytes(), 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 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(), canonical_identifier=channel_state.canonical_identifier, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = token_network.state_transition( token_network_state=channel_settled_iteration.new_state, state_change=channel_batch_unlock_state_change, block_number=unlock_blocknumber, block_hash=factories.make_block_hash(), ) 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_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 test_routing_priority( chain_state, payment_network_state, 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() 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, ) 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
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_channel_data_removed_after_unlock(chain_state, token_network_state, our_address, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() properties, pkey = channel_properties address = properties.partner_state.address channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, ) 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.make_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, 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, ) channel_state_after_closed = channel_closed_iteration.new_state.channelidentifiers_to_channels[ channel_state.identifier] 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=merkleroot( channel_state_after_closed.our_state.merkletree), partner_onchain_locksroot=merkleroot( channel_state_after_closed.partner_state.merkletree), ) 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 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(), canonical_identifier=channel_state.canonical_identifier, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = token_network.state_transition( token_network_state=channel_settled_iteration.new_state, state_change=channel_batch_unlock_state_change, block_number=unlock_blocknumber, block_hash=factories.make_block_hash(), ) 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_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_channel_settle_must_properly_cleanup(channel_properties): 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) properties, _ = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, ) 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