def test_channelstate_get_unlock_proof(): number_of_transfers = 100 lock_amounts = cycle([1, 3, 5, 7, 11]) lock_secrets = [ make_secret(i) for i in range(number_of_transfers) ] block_number = 1000 locked_amount = 0 settle_timeout = 8 merkletree_leaves = [] locked_locks = {} unlocked_locks = {} for lock_amount, lock_secret in zip(lock_amounts, lock_secrets): block_number += 1 locked_amount += lock_amount lock_expiration = block_number + settle_timeout lock_secrethash = sha3(lock_secret) lock = HashTimeLockState( lock_amount, lock_expiration, lock_secrethash, ) merkletree_leaves.append(lock.lockhash) if random.randint(0, 1) == 0: locked_locks[lock_secrethash] = lock else: unlocked_locks[lock_secrethash] = UnlockPartialProofState(lock, lock_secret) end_state = NettingChannelEndState(HOP1, 300) end_state.secrethashes_to_lockedlocks = locked_locks end_state.secrethashes_to_unlockedlocks = unlocked_locks end_state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves)) unlock_proof = channel.get_batch_unlock(end_state) assert len(unlock_proof) == len(end_state.merkletree.layers[LEAVES]) leaves_packed = b''.join(lock.encoded for lock in unlock_proof) recomputed_merkle_tree = MerkleTreeState(compute_layers( merkle_leaves_from_packed_data(leaves_packed), )) assert len(recomputed_merkle_tree.layers[LEAVES]) == len(end_state.merkletree.layers[LEAVES]) computed_merkleroot = merkleroot(recomputed_merkle_tree) assert merkleroot(end_state.merkletree) == computed_merkleroot
def unlock( raiden: "RaidenService", payment_channel: PaymentChannel, end_state: NettingChannelEndState, participant: Address, partner: Address, ) -> None: merkle_tree_leaves = get_batch_unlock(end_state) try: payment_channel.unlock( participant=participant, partner=partner, merkle_tree_leaves=merkle_tree_leaves ) except ChannelOutdatedError as e: log.error(str(e), node=pex(raiden.address))
def unlock( payment_channel: PaymentChannel, end_state: NettingChannelEndState, sender: Address, receiver: Address, given_block_identifier: BlockSpecification, ) -> None: # pragma: no unittest pending_locks = get_batch_unlock(end_state) assert pending_locks, "pending lock set is missing" payment_channel.unlock( sender=sender, receiver=receiver, pending_locks=pending_locks, given_block_identifier=given_block_identifier, )
def handle_contract_send_channelunlock( self, raiden: RaidenService, channel_unlock_event: ContractSendChannelBatchUnlock, ): payment_channel: PaymentChannel = raiden.chain.payment_channel( channel_unlock_event.token_network_identifier, channel_unlock_event.channel_identifier, ) token_network: TokenNetwork = payment_channel.token_network # Fetch on-chain balance hashes for both participants participants_details = token_network.detail_participants( raiden.address, channel_unlock_event.participant, channel_unlock_event.channel_identifier, ) our_details = participants_details.our_details our_locksroot = our_details.locksroot partner_details = participants_details.partner_details partner_locksroot = partner_details.locksroot is_partner_unlock = (partner_details.address == channel_unlock_event.participant and partner_locksroot != EMPTY_HASH) is_our_unlock = (our_details.address == channel_unlock_event.participant and our_locksroot != EMPTY_HASH) if is_partner_unlock: record = raiden.wal.storage.get_latest_state_change_by_data_field({ 'balance_proof.chain_id': raiden.chain.network_id, 'balance_proof.token_network_identifier': to_checksum_address( channel_unlock_event.token_network_identifier, ), 'balance_proof.channel_identifier': channel_unlock_event.channel_identifier, 'balance_proof.sender': to_checksum_address( participants_details.partner_details.address, ), 'balance_proof.locksroot': serialize_bytes(partner_locksroot), }) elif is_our_unlock: record = raiden.wal.storage.get_latest_event_by_data_field({ 'balance_proof.chain_id': raiden.chain.network_id, 'balance_proof.token_network_identifier': to_checksum_address( channel_unlock_event.token_network_identifier, ), 'balance_proof.locksroot': serialize_bytes(our_locksroot), 'channel_identifier': channel_unlock_event.channel_identifier, }) else: raise RaidenUnrecoverableError( 'Failed to find state/event that match current channel locksroots', ) # Replay state changes until a channel state is reached where # this channel state has the participants balance hash. restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=channel_unlock_event.token_address, channel_identifier=channel_unlock_event.channel_identifier, state_change_identifier=record.state_change_identifier, ) # Compute merkle tree leaves from partner state our_state = restored_channel_state.our_state partner_state = restored_channel_state.partner_state if partner_state.address == channel_unlock_event.participant: # Partner account merkle_tree_leaves = get_batch_unlock(partner_state) elif our_state.address == channel_unlock_event.participant: # Our account merkle_tree_leaves = get_batch_unlock(our_state) try: payment_channel.unlock(merkle_tree_leaves) except ChannelOutdatedError as e: log.error( str(e), node=pex(raiden.address), )
def handle_contract_send_channelunlock( self, raiden: RaidenService, channel_unlock_event: ContractSendChannelBatchUnlock, ): token_network_identifier = channel_unlock_event.token_network_identifier channel_identifier = channel_unlock_event.channel_identifier participant = channel_unlock_event.participant token_address = channel_unlock_event.token_address payment_channel: PaymentChannel = raiden.chain.payment_channel( token_network_address=token_network_identifier, channel_id=channel_identifier, ) token_network: TokenNetwork = payment_channel.token_network participants_details = token_network.detail_participants( participant1=raiden.address, participant2=participant, channel_identifier=channel_identifier, ) our_details = participants_details.our_details our_locksroot = our_details.locksroot partner_details = participants_details.partner_details partner_locksroot = partner_details.locksroot is_partner_unlock = ( partner_details.address == participant and partner_locksroot != EMPTY_HASH ) is_our_unlock = ( our_details.address == participant and our_locksroot != EMPTY_HASH ) if is_partner_unlock: state_change_record = get_state_change_with_balance_proof( storage=raiden.wal.storage, chain_id=raiden.chain.network_id, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, balance_hash=partner_details.balance_hash, sender=participants_details.partner_details.address, ) state_change_identifier = state_change_record.state_change_identifier elif is_our_unlock: event_record = get_event_with_balance_proof( storage=raiden.wal.storage, chain_id=raiden.chain.network_id, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, balance_hash=our_details.balance_hash, ) state_change_identifier = event_record.state_change_identifier else: state_change_identifier = 0 if not state_change_identifier: raise RaidenUnrecoverableError( f'Failed to find state/event that match current channel locksroots. ' f'token:{to_checksum_address(token_address)} ' f'token_network:{to_checksum_address(token_network_identifier)} ' f'channel:{channel_identifier} ' f'participant:{to_checksum_address(participant)} ' f'our_locksroot:{to_hex(our_locksroot)} ' f'partner_locksroot:{to_hex(partner_locksroot)} ', ) # Replay state changes until a channel state is reached where # this channel state has the participants balance hash. restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=token_address, channel_identifier=channel_identifier, state_change_identifier=state_change_identifier, ) our_state = restored_channel_state.our_state partner_state = restored_channel_state.partner_state if partner_state.address == participant: merkle_tree_leaves = get_batch_unlock(partner_state) elif our_state.address == participant: merkle_tree_leaves = get_batch_unlock(our_state) try: payment_channel.unlock(merkle_tree_leaves) except ChannelOutdatedError as e: log.error( str(e), node=pex(raiden.address), )
def test_settled_lock(token_addresses, raiden_network, deposit): """ Any transfer following a secret revealed must update the locksroot, so hat an attacker cannot reuse a secret to double claim a lock.""" app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = 30 token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.chain.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) # Using a pending mediated transfer because this allows us to compute the # merkle proof identifier = 1 secret = pending_mediated_transfer( raiden_network, token_network_identifier, amount, identifier, ) # Save the merkle tree leaves from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock claim_lock(raiden_network, identifier, token_network_identifier, secret) # Make a new transfer direct_transfer(app0, app1, token_network_identifier, amount, identifier=1) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) netting_channel = app1.raiden.chain.payment_channel( token_network_identifier, channelstate_0_1.identifier, ) # The direct transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(Exception): netting_channel.unlock( channelstate_0_1.partner_state.address, batch_unlock, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1
def test_settled_lock(token_addresses, raiden_network, deposit): """ Any transfer following a secret reveal must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = 30 token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = hold_event_handler address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.chain.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = 1 target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the merkle tree leaves from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock hold_event_handler.release_secretrequest_for( app1.raiden, secrethash, ) mediated_transfer( initiator_app=app0, target_app=app1, token_network_identifier=token_network_identifier, amount=amount, identifier=2, ) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) netting_channel = app1.raiden.chain.payment_channel( token_network_identifier, channelstate_0_1.identifier, ) # The transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(Exception): netting_channel.unlock( channelstate_0_1.partner_state.address, batch_unlock, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1
def test_settled_lock(token_addresses, raiden_network, deposit): """ Any transfer following a secret reveal must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = 30 token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = hold_event_handler address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.chain.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = 1 target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) secret_available = hold_event_handler.hold_secretrequest_for( secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the merkle tree leaves from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock hold_event_handler.release_secretrequest_for( app1.raiden, secrethash, ) mediated_transfer( initiator_app=app0, target_app=app1, token_network_identifier=token_network_identifier, amount=amount, identifier=2, ) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) netting_channel = app1.raiden.chain.payment_channel( token_network_identifier, channelstate_0_1.identifier, ) # The transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(Exception): netting_channel.unlock( channelstate_0_1.partner_state.address, batch_unlock, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1
def test_settled_lock(token_addresses, raiden_network, deposit): """ Any transfer following a secret reveal must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = PaymentAmount(30) token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address ) assert token_network_address hold_event_handler = app1.raiden.raiden_event_handler address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.proxy_manager.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = 1 target = app1.raiden.address secret = Secret(sha3(target)) secrethash = sha256_secrethash(secret) secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the pending locks from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_address) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock hold_event_handler.release_secretrequest_for(app1.raiden, secrethash) transfer( initiator_app=app0, target_app=app1, token_address=token_address, amount=amount, identifier=PaymentID(2), ) RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) current_block = app0.raiden.rpc_client.block_number() netting_channel = app1.raiden.proxy_manager.payment_channel( canonical_identifier=channelstate_0_1.canonical_identifier ) # The transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(RaidenUnrecoverableError): netting_channel.unlock( sender=channelstate_0_1.our_state.address, receiver=channelstate_0_1.partner_state.address, pending_locks=batch_unlock, given_block_identifier=current_block, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1
def handle_contract_send_channelunlock( self, raiden: RaidenService, channel_unlock_event: ContractSendChannelBatchUnlock, ): token_network_identifier = channel_unlock_event.token_network_identifier channel_identifier = channel_unlock_event.channel_identifier participant = channel_unlock_event.participant token_address = channel_unlock_event.token_address payment_channel: PaymentChannel = raiden.chain.payment_channel( token_network_address=token_network_identifier, channel_id=channel_identifier, ) token_network: TokenNetwork = payment_channel.token_network participants_details = token_network.detail_participants( participant1=raiden.address, participant2=participant, channel_identifier=channel_identifier, ) our_details = participants_details.our_details our_locksroot = our_details.locksroot partner_details = participants_details.partner_details partner_locksroot = partner_details.locksroot is_partner_unlock = (partner_details.address == participant and partner_locksroot != EMPTY_HASH) is_our_unlock = (our_details.address == participant and our_locksroot != EMPTY_HASH) if not is_partner_unlock and not is_our_unlock: # In the case that someone else sent the unlock we do nothing # Check https://github.com/raiden-network/raiden/issues/3152 # for more details log.warning( 'Onchain unlock already mined', token_address=token_address, channel_identifier=channel_identifier, participant=participant, ) return record = get_state_change_or_event_with_balance_proof( storage=raiden.wal.storage, chain_id=raiden.chain.network_id, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, is_our_unlock=is_our_unlock, is_partner_unlock=is_partner_unlock, our_balance_hash=our_details.balance_hash, partner_balance_hash=partner_details.balance_hash, sender=participants_details.partner_details.address, ) if not record.state_change_identifier: log.warning( f'Unlock not done. ' f'Failed to find state/event that match current channel locksroots. ' f'token:{to_checksum_address(token_address)} ' f'token_network:{to_checksum_address(token_network_identifier)} ' f'channel:{channel_identifier} ' f'participant:{to_checksum_address(participant)} ' f'our_locksroot:{to_hex(our_locksroot)} ' f'partner_locksroot:{to_hex(partner_locksroot)} ', ) return # Replay state changes until a channel state is reached where # this channel state has the participants balance hash. restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=token_address, channel_identifier=channel_identifier, state_change_identifier=record.state_change_identifier, ) our_state = restored_channel_state.our_state partner_state = restored_channel_state.partner_state if partner_state.address == participant: merkle_tree_leaves = get_batch_unlock(partner_state) elif our_state.address == participant: merkle_tree_leaves = get_batch_unlock(our_state) try: payment_channel.unlock(merkle_tree_leaves) except ChannelOutdatedError as e: log.error( str(e), node=pex(raiden.address), )
def handle_contract_send_channelunlock( self, raiden: RaidenService, channel_unlock_event: ContractSendChannelBatchUnlock, ): token_network_identifier = channel_unlock_event.token_network_identifier channel_identifier = channel_unlock_event.channel_identifier participant = channel_unlock_event.participant token_address = channel_unlock_event.token_address payment_channel: PaymentChannel = raiden.chain.payment_channel( token_network_address=token_network_identifier, channel_id=channel_identifier, ) token_network: TokenNetwork = payment_channel.token_network participants_details = token_network.detail_participants( participant1=raiden.address, participant2=participant, channel_identifier=channel_identifier, ) our_details = participants_details.our_details our_locksroot = our_details.locksroot partner_details = participants_details.partner_details partner_locksroot = partner_details.locksroot is_partner_unlock = ( partner_details.address == participant and partner_locksroot != EMPTY_HASH ) is_our_unlock = ( our_details.address == participant and our_locksroot != EMPTY_HASH ) if is_partner_unlock: state_change_record = get_state_change_with_balance_proof_by_locksroot( storage=raiden.wal.storage, chain_id=raiden.chain.network_id, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, locksroot=partner_locksroot, sender=participants_details.partner_details.address, ) state_change_identifier = state_change_record.state_change_identifier elif is_our_unlock: event_record = get_event_with_balance_proof_by_locksroot( storage=raiden.wal.storage, chain_id=raiden.chain.network_id, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, locksroot=our_locksroot.balance_hash, ) state_change_identifier = event_record.state_change_identifier else: # In the case that someone else sent the unlock we do nothing # Check https://github.com/raiden-network/raiden/issues/3152 # for more details log.warning( 'Onchain unlock already mined', token_address=token_address, channel_identifier=channel_identifier, participant=participant, ) return if not state_change_identifier: raise RaidenUnrecoverableError( f'Failed to find state/event that match current channel locksroots. ' f'chain_id:{raiden.chain.network_id} ' f'token:{to_checksum_address(token_address)} ' f'token_network:{to_checksum_address(token_network_identifier)} ' f'channel:{channel_identifier} ' f'participant:{to_checksum_address(participant)} ' f'our_locksroot:{to_hex(our_locksroot)} ' f'our_balance_hash:{to_hex(our_details.balance_hash)} ' f'partner_locksroot:{to_hex(partner_locksroot)} ' f'partner_balancehash:{to_hex(partner_details.balance_hash)} ', ) # Replay state changes until a channel state is reached where # this channel state has the participants balance hash. restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=token_address, channel_identifier=channel_identifier, state_change_identifier=state_change_identifier, ) our_state = restored_channel_state.our_state partner_state = restored_channel_state.partner_state if partner_state.address == participant: merkle_tree_leaves = get_batch_unlock(partner_state) elif our_state.address == participant: merkle_tree_leaves = get_batch_unlock(our_state) try: payment_channel.unlock(merkle_tree_leaves) except ChannelOutdatedError as e: log.error( str(e), node=pex(raiden.address), )
def test_settled_lock( token_addresses: List[TokenAddress], raiden_network: List[App], deposit: TokenAmount ) -> None: """ Any transfer following a secret reveal must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = PaymentAmount(30) token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address ) assert token_network_address hold_event_handler = app1.raiden.raiden_event_handler msg = "hold event handler necessary to control messages" assert isinstance(hold_event_handler, HoldRaidenEventHandler), msg address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.proxy_manager.token(token_address, BLOCK_ID_LATEST) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = factories.make_payment_id() target = TargetAddress(app1.raiden.address) secret = factories.make_secret() secrethash = sha256_secrethash(secret) secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the pending locks from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_address) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock hold_event_handler.release_secretrequest_for(app1.raiden, secrethash) transfer( initiator_app=app0, target_app=app1, token_address=token_address, amount=amount, identifier=PaymentID(2), ) # The channel state has to be recovered before the settlement, otherwise # the object is cleared from the node's state. channelstate_1_0 = get_channelstate(app1, app0, token_network_address) RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) current_block = app0.raiden.rpc_client.block_number() netting_channel = app1.raiden.proxy_manager.payment_channel( channel_state=channelstate_1_0, block_identifier=BLOCK_ID_LATEST ) # The transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(RaidenUnrecoverableError): netting_channel.unlock( sender=channelstate_0_1.our_state.address, receiver=channelstate_0_1.partner_state.address, pending_locks=batch_unlock, given_block_identifier=current_block, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1