def test_next_route(): amount = UNIT_TRANSFER_AMOUNT channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) msg = 'an initialized state must use the first valid route' assert state.initiator.channel_identifier == channel1.identifier, msg assert not state.cancelled_channels state_change = ActionCancelRoute( UNIT_REGISTRY_IDENTIFIER, channel1.identifier, available_routes, ) iteration = initiator_manager.state_transition( state, state_change, channel_map, pseudo_random_generator, block_number, ) # HOP3 should be ignored because it doesnt have enough balance assert iteration.new_state.cancelled_channels == [channel1.identifier]
def make_from_route_from_counter(counter): from_channel = factories.make_channel( partner_balance=next(counter), partner_address=factories.HOP1, token_address=factories.make_address(), channel_identifier=next(counter), ) from_route = factories.route_from_channel(from_channel) expiration = factories.UNIT_REVEAL_TIMEOUT + 1 from_transfer = factories.make_signed_transfer_for( from_channel, factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( balance_proof=factories.BalanceProofProperties( transferred_amount=0, token_network_identifier=from_channel.token_network_identifier, ), amount=1, expiration=expiration, secret=sha3(factories.make_secret(next(counter))), initiator=factories.make_address(), target=factories.make_address(), payment_identifier=next(counter), ), sender=factories.HOP1, pkey=factories.HOP1_KEY, ), ) return from_route, from_transfer
def test_init_with_maximum_pending_transfers_exceeded(): channel1 = factories.make_channel( our_balance=2 * MAXIMUM_PENDING_TRANSFERS * UNIT_TRANSFER_AMOUNT, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] pseudo_random_generator = random.Random() transitions = list() block_number = 1 for _ in range(MAXIMUM_PENDING_TRANSFERS + 1): init_state_change = ActionInitInitiator(make_transfer_description(), available_routes) transitions.append(initiator_manager.state_transition( None, init_state_change, channel_map, pseudo_random_generator, block_number, )) failed_transition = transitions.pop() assert all( isinstance(transition.new_state, InitiatorPaymentState) for transition in transitions ) assert failed_transition.new_state is None assert len(failed_transition.events) == 1 assert isinstance(failed_transition.events[0], EventPaymentSentFailed)
def test_events_for_close_secret_unknown(): """ Channel must not be closed when the unsafe region is reached and the secret is not known. """ amount = 3 block_number = 10 expiration = block_number + 30 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) state = TargetTransferState(from_route, from_transfer) events = target.events_for_close(state, from_channel, expiration) assert not events
def _action_init_initiator(self, transfer: TransferDescriptionWithSecretState): channel = self.address_to_channel[transfer.target] if transfer.secrethash not in self.expected_expiry: self.expected_expiry[transfer.secrethash] = self.block_number + 10 return ActionInitInitiator( transfer, [factories.route_from_channel(channel)], )
def test_handle_inittarget(): """ Init transfer must send a secret request if the expiration is valid. """ amount = 3 block_number = 1 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET pseudo_random_generator = random.Random() from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer( amount, initiator, target_address, expiration, UNIT_SECRET, channel_identifier=from_channel.identifier, ) state_change = ActionInitTarget( from_route, from_transfer, ) iteration = target.handle_inittarget( state_change, from_channel, pseudo_random_generator, block_number, ) events = iteration.events assert events assert isinstance(events[0], SendSecretRequest) assert events[0].payment_identifier == from_transfer.payment_identifier assert events[0].amount == from_transfer.lock.amount assert events[0].secrethash == from_transfer.lock.secrethash assert events[0].recipient == initiator
def test_events_for_onchain_secretreveal(): """ Secret must be registered on-chain when the unsafe region is reached and the secret is known. """ amount = 3 block_number = 10 expiration = block_number + 30 initiator = HOP1 target_address = UNIT_TRANSFER_TARGET from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) channel.register_secret(from_channel, UNIT_SECRET, UNIT_SECRETHASH) safe_to_wait = expiration - from_channel.reveal_timeout - 1 unsafe_to_wait = expiration - from_channel.reveal_timeout state = TargetTransferState(from_route, from_transfer) events = target.events_for_onchain_secretreveal(state, from_channel, safe_to_wait) assert not events events = target.events_for_onchain_secretreveal(state, from_channel, unsafe_to_wait) assert events assert isinstance(events[0], ContractSendSecretReveal) assert events[0].secret == UNIT_SECRET
def setup_initiator_tests( amount=UNIT_TRANSFER_AMOUNT, partner_balance=EMPTY, our_address=EMPTY, partner_address=EMPTY, block_number=1, ) -> InitiatorSetup: """Commonly used setup code for initiator manager and channel""" prng = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=partner_balance, our_address=our_address, partner_address=partner_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, prng, block_number, ) lock = channel.get_lock( channel1.our_state, current_state.initiator.transfer_description.secrethash, ) setup = InitiatorSetup( current_state=current_state, block_number=block_number, channel=channel1, channel_map=channel_map, available_routes=available_routes, prng=prng, lock=lock, ) return setup
def test_init_with_usable_routes(): channel1 = factories.make_channel( our_balance=UNIT_TRANSFER_AMOUNT, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] pseudo_random_generator = random.Random() init_state_change = ActionInitInitiator( factories.UNIT_TRANSFER_DESCRIPTION, available_routes, ) block_number = 1 transition = initiator_manager.state_transition( None, init_state_change, channel_map, pseudo_random_generator, block_number, ) assert isinstance(transition.new_state, InitiatorPaymentState) assert transition.events, 'we have a valid route, the mediated transfer event must be emitted' payment_state = transition.new_state assert payment_state.initiator.transfer_description == factories.UNIT_TRANSFER_DESCRIPTION mediated_transfers = [e for e in transition.events if isinstance(e, SendLockedTransfer)] assert len(mediated_transfers) == 1, 'mediated_transfer should /not/ split the transfer' send_mediated_transfer = mediated_transfers[0] transfer = send_mediated_transfer.transfer expiration = initiator.get_initial_lock_expiration(block_number, channel1.reveal_timeout) assert transfer.balance_proof.token_network_identifier == channel1.token_network_identifier assert transfer.lock.amount == factories.UNIT_TRANSFER_DESCRIPTION.amount assert transfer.lock.expiration == expiration assert transfer.lock.secrethash == factories.UNIT_TRANSFER_DESCRIPTION.secrethash assert send_mediated_transfer.recipient == channel1.partner_state.address
def test_handle_inittarget_bad_expiration(): """ Init transfer must do nothing if the expiration is bad. """ block_number = 1 amount = 3 initiator = factories.HOP1 target_address = UNIT_TRANSFER_TARGET pseudo_random_generator = random.Random() from_channel = factories.make_channel( our_address=target_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, target_address, expiration, UNIT_SECRET, ) channel.handle_receive_lockedtransfer( from_channel, from_transfer, ) state_change = ActionInitTarget(from_route, from_transfer) iteration = target.handle_inittarget( state_change, from_channel, pseudo_random_generator, block_number, ) assert must_contain_entry(iteration.events, EventUnlockClaimFailed, {})
def make_target_state(our_address, amount, block_number, initiator, expiration=None): from_channel = factories.make_channel( our_address=our_address, partner_address=UNIT_TRANSFER_SENDER, partner_balance=amount, ) from_route = factories.route_from_channel(from_channel) if expiration is None: expiration = from_channel.reveal_timeout + block_number + 1 from_transfer = factories.make_signed_transfer_for( from_channel, amount, initiator, our_address, expiration, UNIT_SECRET, ) state = TargetTransferState(from_route, from_transfer) return from_channel, state
def test_initiator_lock_expired(): amount = UNIT_TRANSFER_AMOUNT * 2 block_number = 1 refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) pseudo_random_generator = random.Random() channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), ] block_number = 10 current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) transfer = current_state.initiator.transfer assert transfer.lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks # Trigger lock expiry state_change = Block( block_number=transfer.lock.expiration + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert events.must_contain_entry( iteration.events, SendLockExpired, { 'balance_proof': { 'nonce': 2, 'transferred_amount': 0, 'locked_amount': 0, }, 'secrethash': transfer.lock.secrethash, 'recipient': channel1.partner_state.address, }) assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Create 2 other transfers transfer2_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer2'), channel_map, pseudo_random_generator, 30, ) transfer2_lock = transfer2_state.initiator.transfer.lock transfer3_state = make_initiator_manager_state( available_routes, make_transfer_description('transfer3'), channel_map, pseudo_random_generator, 32, ) transfer3_lock = transfer3_state.initiator.transfer.lock assert len(channel1.our_state.secrethashes_to_lockedlocks) == 2 assert transfer2_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks expiration_block_number = transfer2_lock.expiration + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK block = Block( block_number=expiration_block_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = initiator_manager.state_transition( transfer2_state, block, channel_map, pseudo_random_generator, expiration_block_number, ) # Transfer 2 expired assert transfer2_lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks # Transfer 3 is still there assert transfer3_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks
def test_refund_transfer_next_route(): amount = UNIT_TRANSFER_AMOUNT our_address = factories.ADDR refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=our_address, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer refund_transfer = factories.make_signed_transfer( amount, our_address, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) assert channel1.partner_state.address == refund_address state_change = ReceiveTransferRefundCancelRoute( routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert iteration.new_state is not None route_cancelled = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) new_transfer = next(e for e in iteration.events if isinstance(e, SendLockedTransfer)) assert route_cancelled, 'The previous transfer must be cancelled' assert new_transfer, 'No mediated transfer event emitted, should have tried a new route' msg = 'the new transfer must use a new secret / secrethash' assert new_transfer.transfer.lock.secrethash != refund_transfer.lock.secrethash, msg assert iteration.new_state.initiator is not None
def test_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_payer_enter_danger_zone_with_transfer_payed(): """ A mediator may have paid the next hop (payee), and didn't get paid by the previous hop (payer). When this happens, an assertion must not be hit, because it means the transfer must be withdrawn on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ amount = 10 block_number = 5 target = HOP2 expiration = 30 pseudo_random_generator = random.Random() payer_channel = factories.make_channel( partner_balance=amount, partner_address=UNIT_TRANSFER_SENDER, token_address=UNIT_TOKEN_ADDRESS, ) payer_transfer = factories.make_signed_transfer_for( payer_channel, amount, HOP1, target, expiration, UNIT_SECRET, ) channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, ) channelmap = { channel1.identifier: channel1, payer_channel.identifier: payer_channel, } possible_routes = [factories.route_from_channel(channel1)] mediator_state = MediatorTransferState(UNIT_SECRETHASH) initial_iteration = mediator.mediate_transfer( UNIT_REGISTRY_IDENTIFIER, mediator_state, possible_routes, payer_channel, channelmap, pseudo_random_generator, payer_transfer, 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 + 1): block_state_change = Block(block_number) block_iteration = mediator.handle_block( channelmap, new_state, block_state_change, block_number, ) new_state = block_iteration.new_state # send the balance proof, transitioning the payee state to paid assert new_state.transfers_pair[0].payee_state == 'payee_pending' receive_secret = ReceiveSecretReveal( UNIT_SECRET, channel1.partner_state.address, ) paid_iteration = mediator.state_transition( new_state, receive_secret, channelmap, 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(expired_block_number) block_iteration = mediator.handle_block( channelmap, paid_state, expired_block_state_change, expired_block_number, )
def test_target_receive_lock_expired(): lock_amount = 7 block_number = 1 initiator = factories.HOP6 pseudo_random_generator = random.Random() our_balance = 100 our_address = factories.make_address() partner_balance = 130 from_channel = factories.make_channel( our_address=our_address, our_balance=our_balance, partner_address=UNIT_TRANSFER_SENDER, partner_balance=partner_balance, ) from_route = factories.route_from_channel(from_channel) expiration = block_number + from_channel.settle_timeout - from_channel.reveal_timeout from_transfer = factories.make_signed_transfer_for( channel_state=from_channel, amount=lock_amount, initiator=initiator, target=our_address, expiration=expiration, secret=UNIT_SECRET, ) init = ActionInitTarget( from_route, from_transfer, ) init_transition = target.state_transition( None, init, from_channel, pseudo_random_generator, block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == from_route assert init_transition.new_state.transfer == from_transfer balance_proof = factories.make_signed_balance_proof( 2, from_transfer.balance_proof.transferred_amount, 0, from_transfer.balance_proof.token_network_identifier, from_channel.identifier, EMPTY_MERKLE_ROOT, from_transfer.lock.secrethash, sender_address=UNIT_TRANSFER_SENDER, private_key=UNIT_TRANSFER_PKEY, ) lock_expired_state_change = ReceiveLockExpired( HOP1, balance_proof, from_transfer.lock.secrethash, 1, ) block_before_confirmed_expiration = expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS - 1 iteration = target.state_transition( init_transition.new_state, lock_expired_state_change, from_channel, pseudo_random_generator, block_before_confirmed_expiration, ) assert not must_contain_entry(iteration.events, SendProcessed, {}) block_lock_expired = block_before_confirmed_expiration + 1 iteration = target.state_transition( init_transition.new_state, lock_expired_state_change, from_channel, pseudo_random_generator, block_lock_expired, ) assert must_contain_entry(iteration.events, SendProcessed, {})
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_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_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_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_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_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_refund_transfer_no_more_routes(): amount = UNIT_TRANSFER_AMOUNT block_number = 1 refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=UNIT_TRANSFER_INITIATOR, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer channel_identifier = current_state.initiator.channel_identifier channel_state = channel_map[channel_identifier] refund_transfer = factories.make_signed_transfer( amount, original_transfer.initiator, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) state_change = ReceiveTransferRefundCancelRoute( sender=channel_state.partner_state.address, routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert iteration.new_state is None unlocked_failed = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) sent_failed = next(e for e in iteration.events if isinstance(e, EventPaymentSentFailed)) assert unlocked_failed assert sent_failed
def test_refund_transfer_next_route(): amount = UNIT_TRANSFER_AMOUNT our_address = factories.ADDR refund_pkey, refund_address = factories.make_privkey_address() pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, partner_balance=amount, our_address=our_address, partner_address=refund_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel2 = factories.make_channel( our_balance=0, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel3 = factories.make_channel( our_balance=amount, our_address=our_address, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = { channel1.identifier: channel1, channel2.identifier: channel2, channel3.identifier: channel3, } available_routes = [ factories.route_from_channel(channel1), factories.route_from_channel(channel2), factories.route_from_channel(channel3), ] block_number = 10 current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) original_transfer = current_state.initiator.transfer refund_transfer = factories.make_signed_transfer( amount, our_address, original_transfer.target, original_transfer.lock.expiration, UNIT_SECRET, payment_identifier=original_transfer.payment_identifier, channel_identifier=channel1.identifier, pkey=refund_pkey, sender=refund_address, ) assert channel1.partner_state.address == refund_address state_change = ReceiveTransferRefundCancelRoute( routes=available_routes, transfer=refund_transfer, secret=random_secret(), ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert iteration.new_state is not None route_cancelled = next(e for e in iteration.events if isinstance(e, EventUnlockFailed)) new_transfer = next(e for e in iteration.events if isinstance(e, SendLockedTransfer)) assert route_cancelled, 'The previous transfer must be cancelled' assert new_transfer, 'No mediated transfer event emitted, should have tried a new route' msg = 'the new transfer must use a new secret / secrethash' assert new_transfer.transfer.lock.secrethash != refund_transfer.lock.secrethash, msg assert iteration.new_state.initiator is not None
def test_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_state_transition(): """ Happy case testing. """ lock_amount = 7 block_number = 1 initiator = factories.HOP6 pseudo_random_generator = random.Random() our_balance = 100 our_address = factories.make_address() partner_balance = 130 from_channel = factories.make_channel( our_address=our_address, our_balance=our_balance, partner_address=UNIT_TRANSFER_SENDER, partner_balance=partner_balance, ) from_route = factories.route_from_channel(from_channel) expiration = block_number + from_channel.settle_timeout from_transfer = factories.make_signed_transfer_for( from_channel, lock_amount, initiator, our_address, expiration, UNIT_SECRET, ) init = ActionInitTarget( from_route, from_transfer, ) init_transition = target.state_transition( None, init, from_channel, pseudo_random_generator, block_number, ) assert init_transition.new_state is not None assert init_transition.new_state.route == from_route assert init_transition.new_state.transfer == from_transfer first_new_block = Block(block_number + 1) first_block_iteration = target.state_transition( init_transition.new_state, first_new_block, from_channel, pseudo_random_generator, first_new_block.block_number, ) secret_reveal = ReceiveSecretReveal(factories.UNIT_SECRET, initiator) reveal_iteration = target.state_transition( first_block_iteration.new_state, secret_reveal, from_channel, pseudo_random_generator, first_new_block, ) assert reveal_iteration.events second_new_block = Block(block_number + 2) iteration = target.state_transition( init_transition.new_state, second_new_block, from_channel, pseudo_random_generator, second_new_block.block_number, ) assert not iteration.events nonce = from_transfer.balance_proof.nonce + 1 transferred_amount = lock_amount locksroot = EMPTY_MERKLE_ROOT invalid_message_hash = b'\x00' * 32 locked_amount = 0 balance_proof = factories.make_signed_balance_proof( nonce, transferred_amount, locked_amount, from_channel.token_network_identifier, from_route.channel_identifier, locksroot, invalid_message_hash, UNIT_TRANSFER_PKEY, UNIT_TRANSFER_SENDER, ) balance_proof_state_change = ReceiveUnlock( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, balance_proof=balance_proof, ) proof_iteration = target.state_transition( init_transition.new_state, balance_proof_state_change, from_channel, pseudo_random_generator, block_number + 2, ) assert proof_iteration.new_state is None
def test_mediator_task_view(): """Same as above for mediator tasks.""" secret1 = factories.make_secret(1) locked_amount1 = 11 payee_transfer = factories.create( factories.LockedTransferProperties(secret=secret1)) payer_transfer = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( secret=secret1, payment_identifier=1, balance_proof=factories.BalanceProofProperties( locked_amount=locked_amount1, ), ), )) secrethash1 = payee_transfer.lock.secrethash initiator = payee_transfer.initiator initiator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=initiator, balance=100), )) routes = [factories.route_from_channel(initiator_channel)] transfer_state1 = MediatorTransferState(secrethash=secrethash1, routes=routes) transfer_state1.transfers_pair.append( MediationPairState( payer_transfer=payer_transfer, payee_transfer=payee_transfer, payee_address=payee_transfer.target, )) task1 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state1, ) secret2 = factories.make_secret(2) locked_amount2 = 13 transfer2 = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( secret=secret2, payment_identifier=2, balance_proof=factories.BalanceProofProperties( locked_amount=locked_amount2, ), ), )) secrethash2 = transfer2.lock.secrethash transfer_state2 = MediatorTransferState(secrethash=secrethash2, routes=routes) transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2) task2 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state2, ) payment_mapping = {secrethash1: task1, secrethash2: task2} view = transfer_tasks_view(payment_mapping) assert len(view) == 2 if view[0].get('payment_identifier') == '1': pending_transfer, waiting_transfer = view else: waiting_transfer, pending_transfer = view assert pending_transfer.get('role') == waiting_transfer.get( 'role') == 'mediator' assert pending_transfer.get('payment_identifier') == '1' assert waiting_transfer.get('payment_identifier') == '2' assert pending_transfer.get('locked_amount') == str(locked_amount1) assert waiting_transfer.get('locked_amount') == str(locked_amount2)
def test_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_state_wait_secretrequest_invalid_amount_and_sender(): amount = UNIT_TRANSFER_AMOUNT block_number = 1 pseudo_random_generator = random.Random() channel1 = factories.make_channel( our_balance=amount, token_address=UNIT_TOKEN_ADDRESS, token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS, ) channel_map = {channel1.identifier: channel1} available_routes = [factories.route_from_channel(channel1)] current_state = make_initiator_manager_state( available_routes, factories.UNIT_TRANSFER_DESCRIPTION, channel_map, pseudo_random_generator, block_number, ) lock = channel.get_lock( channel1.our_state, current_state.initiator.transfer_description.secrethash, ) state_change = ReceiveSecretRequest( UNIT_TRANSFER_IDENTIFIER, lock.amount + 1, lock.expiration, lock.secrethash, UNIT_TRANSFER_INITIATOR, ) iteration = initiator_manager.state_transition( current_state, state_change, channel_map, pseudo_random_generator, block_number, ) assert len(iteration.events) == 0 assert iteration.new_state.initiator.received_secret_request is False # Now the proper target sends the message, this should be applied state_change_2 = ReceiveSecretRequest( UNIT_TRANSFER_IDENTIFIER, lock.amount, lock.expiration, lock.secrethash, UNIT_TRANSFER_TARGET, ) iteration2 = initiator_manager.state_transition( iteration.new_state, state_change_2, channel_map, pseudo_random_generator, block_number, ) assert iteration2.new_state.initiator.received_secret_request is True assert isinstance(iteration2.events[0], SendSecretReveal)