def contractreceivechannelsettled_from_event( channel_settle_state: ChannelSettleState, event: DecodedEvent) -> ContractReceiveChannelSettled: data = event.event_data block_number = data["block_number"] block_hash = data["block_hash"] transaction_hash = data["transaction_hash"] # For saving gas, LOCKSROOT_OF_NO_LOCKS is stored as EMPTY_HASH onchain if channel_settle_state.our_locksroot == EMPTY_LOCKSROOT: our_locksroot = LOCKSROOT_OF_NO_LOCKS else: our_locksroot = channel_settle_state.our_locksroot if channel_settle_state.partner_locksroot == EMPTY_LOCKSROOT: partner_locksroot = LOCKSROOT_OF_NO_LOCKS else: partner_locksroot = channel_settle_state.partner_locksroot return ContractReceiveChannelSettled( transaction_hash=transaction_hash, canonical_identifier=channel_settle_state.canonical_identifier, our_onchain_locksroot=our_locksroot, partner_onchain_locksroot=partner_locksroot, block_number=block_number, block_hash=block_hash, )
def test_channel_cleared_after_our_unlock(): pseudo_random_generator = random.Random() our_model, _ = create_model(balance=700, num_pending_locks=1) partner_model, partner_key1 = create_model(balance=700, num_pending_locks=0) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() 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(), ) assert settle_channel.our_onchain_locksroot != LOCKSROOT_OF_NO_LOCKS assert settle_channel.partner_onchain_locksroot == LOCKSROOT_OF_NO_LOCKS 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, ) 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 = "partner did not have any locks in the pending locks, channel should have been cleaned" assert iteration.new_state is None, msg
def test_channelstate_unlock(): """The node must call unlock after the channel is settled""" our_model1, _ = create_model(70) partner_model1, privkey2 = create_model(100) channel_state = create_channel_from_models(our_model1, partner_model1) lock_amount = 10 lock_expiration = 100 lock_secret = sha3(b'test_channelstate_lockedtransfer_overspent') lock_secrethash = sha3(lock_secret) lock = HashTimeLockState( lock_amount, lock_expiration, lock_secrethash, ) nonce = 1 transferred_amount = 0 receive_lockedtransfer = make_receive_transfer_mediated( channel_state, privkey2, nonce, transferred_amount, lock, ) is_valid, _, msg = channel.handle_receive_lockedtransfer( channel_state, receive_lockedtransfer, ) assert is_valid, msg channel.register_secret(channel_state, lock_secret, lock_secrethash) closed_block_number = lock_expiration - channel_state.reveal_timeout - 1 close_state_change = ContractReceiveChannelClosed( channel_state.token_network_identifier, channel_state.identifier, partner_model1.participant_address, closed_block_number, ) iteration = channel.handle_channel_closed(channel_state, close_state_change) assert not must_contain_entry(iteration.events, ContractSendChannelBatchUnlock, {}) settle_block_number = lock_expiration + channel_state.reveal_timeout + 1 settle_state_change = ContractReceiveChannelSettled( channel_state.token_network_identifier, channel_state.identifier, settle_block_number, ) iteration = channel.handle_channel_settled( channel_state, settle_state_change, settle_block_number, ) assert must_contain_entry(iteration.events, ContractSendChannelBatchUnlock, {})
def test_channel_settle_must_properly_cleanup(): open_block_number = 10 pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) amount = 30 our_balance = amount + 50 channel_state = factories.make_channel(our_balance=our_balance) channel_new_state_change = ContractReceiveChannelNew( token_network_id, channel_state) channel_new_iteration = token_network.state_transition( token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( token_network_id, channel_state.identifier, channel_state.partner_state.address, closed_block_number, ) channel_closed_iteration = token_network.state_transition( channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( token_network_id, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert channel_state.identifier not in ids_to_channels
def 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 settle_channel(self, partner): channel = self.address_to_channel[partner] channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( chain_identifier=channel.chain_id, token_network_address=channel.token_network_address, channel_identifier=channel.identifier, ), block_number=self.block_number + 1, block_hash=factories.make_block_hash(), our_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) node.state_transition(self.chain_state, channel_settled_state_change)
def test_is_transaction_effect_satisfied(chain_state, token_network_id, netting_channel_state): canonical_identifier = netting_channel_state.canonical_identifier assert token_network_id == canonical_identifier.token_network_address transaction = ContractSendChannelBatchUnlock( canonical_identifier=canonical_identifier, participant=netting_channel_state.partner_state.address, triggered_by_block_hash=make_block_hash(), ) state_change = ContractReceiveChannelBatchUnlock( transaction_hash=UNIT_SECRETHASH, canonical_identifier=canonical_identifier, participant=HOP1, partner=HOP2, locksroot=EMPTY_MERKLE_ROOT, unlocked_amount=0, returned_tokens=0, block_number=1, block_hash=make_block_hash(), ) # unlock for a channel in which this node is not a participant must return False assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # now call normally with us being the partner and not the participant state_change.partner = netting_channel_state.partner_state.address state_change.participant = netting_channel_state.our_state.address assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # finally call with us being the participant and not the partner which should check out state_change.participant = netting_channel_state.partner_state.address state_change.partner = netting_channel_state.our_state.address # ContractSendChannelBatchUnlock would only be satisfied if both sides are unlocked # and if the channel was cleared assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) channel_settled = ContractReceiveChannelSettled( transaction_hash=bytes(32), canonical_identifier=canonical_identifier, our_onchain_locksroot=EMPTY_MERKLE_ROOT, partner_onchain_locksroot=EMPTY_MERKLE_ROOT, block_number=1, block_hash=make_block_hash(), ) iteration = state_transition(chain_state=chain_state, state_change=channel_settled) assert is_transaction_effect_satisfied(iteration.new_state, transaction, state_change)
def handle_channel_settled(raiden, event, current_block_number): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = event.event_data['channel_identifier'] channel_state = views.get_channelstate_by_token_network_identifier( views.state_from_raiden(raiden), token_network_identifier, channel_identifier, ) if channel_state: channel_settled = ContractReceiveChannelSettled( token_network_identifier, channel_identifier, data['block_number'], ) raiden.handle_state_change(channel_settled, current_block_number)
def test_channel_cleared_after_our_unlock(): our_model, _ = create_model(balance=700, merkletree_width=1) partner_model, partner_key1 = create_model(balance=700, merkletree_width=0) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() def make_unlock(unlock_end, partner_end): batch_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, participant=partner_end.address, partner=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=merkleroot(channel_state.our_state.merkletree), partner_onchain_locksroot=merkleroot( channel_state.partner_state.merkletree), block_number=1, block_hash=make_block_hash(), ) assert settle_channel.our_onchain_locksroot is not EMPTY_MERKLE_ROOT assert settle_channel.partner_onchain_locksroot is EMPTY_MERKLE_ROOT iteration = channel.state_transition(channel_state, settle_channel, block_number, block_hash) batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state) iteration = channel.state_transition(iteration.new_state, batch_unlock, block_number, block_hash) msg = "partner did not have any locks in the merkletree, channel should have been cleaned" assert iteration.new_state is None, msg
def handle_channel_settled(raiden, event): payment_network_identifier = raiden.default_registry.address data = event.event_data channel_identifier = event.originating_contract channel_state = views.search_for_channel( views.state_from_raiden(raiden), payment_network_identifier, channel_identifier, ) if channel_state: channel_settled = ContractReceiveChannelSettled( payment_network_identifier, channel_state.token_address, channel_identifier, data['block_number'], ) raiden.handle_state_change(channel_settled)
def handle_channel_settled(raiden, event): registry_address = event.event_data['registry_address'] data = event.event_data channel_identifier = event.originating_contract channel_state = views.search_for_channel( views.state_from_raiden(raiden), registry_address, channel_identifier, ) if channel_state: channel_settled = ContractReceiveChannelSettled( registry_address, channel_state.token_address, channel_identifier, data['block_number'], ) raiden.handle_state_change(channel_settled)
def handle_channel_settled(raiden: RaidenService, event: Event): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = data['args']['channel_identifier'] transaction_hash = data['transaction_hash'] channel_state = views.get_channelstate_by_token_network_identifier( views.state_from_raiden(raiden), token_network_identifier, channel_identifier, ) if channel_state: channel_settled = ContractReceiveChannelSettled( transaction_hash=transaction_hash, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, block_number=data['block_number'], ) raiden.handle_state_change(channel_settled)
def handle_channel_settled(raiden, event, current_block_number): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = event.event_data['channel_identifier'] transaction_hash = data['transactionHash'] assert transaction_hash, 'A mined transaction must have the hash field' channel_state = views.get_channelstate_by_token_network_identifier( views.state_from_raiden(raiden), token_network_identifier, channel_identifier, ) if channel_state: channel_settled = ContractReceiveChannelSettled( transaction_hash, token_network_identifier, channel_identifier, data['block_number'], ) raiden.handle_state_change(channel_settled, current_block_number)
def handle_channel_settled(raiden, event, current_block_number): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = event.event_data['channel_identifier'] channel_state = views.get_channelstate_by_token_network_identifier( views.state_from_raiden(raiden), token_network_identifier, channel_identifier, ) if channel_state: from_address = raiden.chain.client.get_transaction_from( event.event_data['transactionHash'], ) assert from_address, 'A mined transaction must have the from field' channel_settled = ContractReceiveChannelSettled( from_address, token_network_identifier, channel_identifier, data['block_number'], ) raiden.handle_state_change(channel_settled, current_block_number)
def handle_channel_settled(raiden: "RaidenService", event: Event): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = data["args"]["channel_identifier"] block_number = data["block_number"] block_hash = data["block_hash"] transaction_hash = data["transaction_hash"] chain_state = views.state_from_raiden(raiden) # TODO fixme mmartinez7 what about when is a light client? channel_state = views.get_channelstate_by_canonical_identifier_and_address( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), address=raiden.address, ) # This may happen for two reasons: # - This node is not a participant for the given channel (normal operation, # the event should be ignored). # - Something went wrong in our code and the channel state was cleared # before settle (a bug, this should raise an exception on development # mode). # Because we cannot distinguish the two cases, assume the channel is not of # interest and ignore the event. if not channel_state: return # Recover the locksroot from the blockchain to fix data races. Check # get_onchain_locksroots for details. try: # First try to query the unblinded state. This way the # ContractReceiveChannelSettled's locksroots will match the values # provided during settle. our_locksroot, partner_locksroot = get_onchain_locksroots( chain=raiden.chain, canonical_identifier=channel_state.canonical_identifier, participant1=channel_state.our_state.address, participant2=channel_state.partner_state.address, block_identifier=block_hash, ) except ValueError: # State pruning handling. The block which generate the ChannelSettled # event may have been pruned, because of this the RPC call will raises # a ValueError. # # The solution is to query the channel's state from the latest block, # this /may/ create a ContractReceiveChannelSettled with the wrong # locksroot (i.e. not the locksroot used during the call to settle). # However this is fine, because at this point the channel is settled, # it is known that the locksroot can not be reverted without an unlock, # and because the unlocks are fare it doesn't matter who called it, # only if there are tokens locked in the settled channel. our_locksroot, partner_locksroot = get_onchain_locksroots( chain=raiden.chain, canonical_identifier=channel_state.canonical_identifier, participant1=channel_state.our_state.address, participant2=channel_state.partner_state.address, block_identifier="latest", ) if raiden.address == channel_state.our_state.address: channel_settled = ContractReceiveChannelSettled( transaction_hash=transaction_hash, canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=our_locksroot, partner_onchain_locksroot=partner_locksroot, block_number=block_number, block_hash=block_hash, participant1=channel_state.our_state.address) raiden.handle_and_track_state_change(channel_settled) else: channel_settled = ContractReceiveChannelSettledLight( transaction_hash=transaction_hash, canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=our_locksroot, partner_onchain_locksroot=partner_locksroot, block_number=block_number, block_hash=block_hash, participant1=channel_state.our_state.address, participant2=channel_state.partner_state.address) raiden.handle_and_track_state_change(channel_settled)
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() 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_mediator = ActionInitMediator(routes=[from_route], from_route=from_route, from_transfer=mediated_transfer) node.state_transition(chain_state, init_mediator, None) 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 block_number = closed_block_number + 1 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, participant=address, partner=our_address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=block_number, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = node.state_transition( chain_state=chain_state, state_change=channel_batch_unlock_state_change, storage=None) 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, storage=None) 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() 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, ) 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, None) 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 # 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, ) 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_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, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, channel_state, ) 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, token_network_address=token_network_state.address, ) 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, ) 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_data_removed_after_unlock( chain_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey, address = factories.make_privkey_address() amount = 30 our_balance = amount + 50 channel_state = factories.make_channel( our_balance=our_balance, our_address=our_address, partner_balance=our_balance, partner_address=address, token_network_identifier=token_network_state.address, ) payment_network_identifier = factories.make_payment_network_identifier() channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), token_network_state.address, channel_state, open_block_number, ) channel_new_iteration = token_network.state_transition( payment_network_identifier, token_network_state, channel_new_state_change, pseudo_random_generator, open_block_number, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) lock = HashTimeLockState( lock_amount, lock_expiration, lock_secrethash, ) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock, ) from_route = factories.route_from_channel(channel_state) init_target = ActionInitTarget( from_route, mediated_transfer, ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 channel_close_state_change = ContractReceiveChannelClosed( factories.make_transaction_hash(), channel_state.partner_state.address, token_network_state.address, channel_state.identifier, closed_block_number, ) channel_closed_iteration = token_network.state_transition( payment_network_identifier, channel_new_iteration.new_state, channel_close_state_change, pseudo_random_generator, closed_block_number, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( factories.make_transaction_hash(), token_network_state.address, channel_state.identifier, settle_block_number, ) channel_settled_iteration = token_network.state_transition( payment_network_identifier, channel_closed_iteration.new_state, channel_settled_state_change, pseudo_random_generator, closed_block_number, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels unlock_blocknumber = settle_block_number + 5 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, participant=our_address, partner=address, locksroot=lock_secrethash, unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, ) channel_unlock_iteration = token_network.state_transition( payment_network_identifier, channel_settled_iteration.new_state, channel_batch_unlock_state_change, pseudo_random_generator, unlock_blocknumber, ) token_network_state_after_unlock = channel_unlock_iteration.new_state ids_to_channels = token_network_state_after_unlock.channelidentifiers_to_channels assert len(ids_to_channels) == 0
def test_multiple_channel_states(chain_state, token_network_state, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = keccak(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( from_hop=from_hop, transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels # Create new channel while the previous one is pending unlock new_channel_properties = factories.create_properties( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier()), defaults=properties, ) new_channel_state = factories.create(new_channel_properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=new_channel_state, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_new_open = channel_new_iteration.new_state ids_to_channels = token_network_state_after_new_open.channelidentifiers_to_channels assert len(ids_to_channels) == 2 assert channel_state.identifier in ids_to_channels
def test_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 = keccak(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) 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_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 = keccak(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( 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_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_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, 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, ) 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 handle_channel_settled(raiden: 'RaidenService', event: Event): data = event.event_data token_network_identifier = event.originating_contract channel_identifier = data['args']['channel_identifier'] block_number = data['block_number'] block_hash = data['block_hash'] transaction_hash = data['transaction_hash'] chain_state = views.state_from_raiden(raiden) channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), ) # This may happen for two reasons: # - This node is not a participant for the given channel (normal operation, # the event should be ignored). # - Something went wrong in our code and the channel state was cleared # before settle (a bug, this should raise an exception on development # mode). # Because we cannot distinguish the two cases, assume the channel is not of # interest and ignore the event. if not channel_state: return """ This is resolving a corner case where the current node view of the channel state does not reflect what the blockchain contains. The corner case goes as follows in a setup of nodes: A -> B: - A sends out a LockedTransfer to B - B sends a refund to A - B goes offline - A sends LockExpired to B Here: (1) the lock is removed from A's state (2) B never received the message - A closes the channel with B's refund - B comes back online and calls updateNonClosingBalanceProof with A's LockedTransfer (LockExpired was never processed). - When channel is settled, B unlocks it's refund transfer lock provided that it gains from doing so. - A does NOT try to unlock its lock because its side of the channel state is empty (lock expired and was removed). The above is resolved by providing the state machine with the onchain locksroots for both participants in the channel so that the channel state is updated to store these locksroots. In `raiden_event_handler:handle_contract_send_channelunlock`, those values are used to restore the channel state back to where the locksroots values existed and this channel state is used to calculate the gain and potentially perform unlocks in case there is value to be gained. """ canonical_identifier = CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ) our_locksroot, partner_locksroot = get_onchain_locksroots( chain=raiden.chain, canonical_identifier=canonical_identifier, participant1=channel_state.our_state.address, participant2=channel_state.partner_state.address, block_identifier=block_hash, ) channel_settled = ContractReceiveChannelSettled( transaction_hash=transaction_hash, canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=our_locksroot, partner_onchain_locksroot=partner_locksroot, block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(channel_settled)
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
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_channel_cleared_after_two_unlocks(): our_model, _ = create_model(balance=700, merkletree_width=1) partner_model, partner_key1 = create_model(balance=700, merkletree_width=1) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() def make_unlock(unlock_end, partner_end): batch_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, participant=partner_end.address, partner=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=merkleroot(channel_state.our_state.merkletree), partner_onchain_locksroot=merkleroot(channel_state.partner_state.merkletree), block_number=1, block_hash=make_block_hash(), ) iteration = channel.state_transition(channel_state, settle_channel, block_number, block_hash) msg = "both participants have pending locks, merkleroot must not be empty" assert iteration.new_state.our_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state) iteration = channel.state_transition( iteration.new_state, batch_unlock, block_number, block_hash ) msg = "all of our locks has been unlocked, onchain state must be updated" assert iteration.new_state.our_state.onchain_locksroot is EMPTY_MERKLE_ROOT, msg msg = "partner has pending locks, the merkleroot must not be cleared" assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, 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( iteration.new_state, batch_unlock, block_number, block_hash ) msg = "partner has pending locks, the merkleroot must not be cleared" assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, 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( iteration.new_state, make_unlock(channel_state.partner_state, channel_state.our_state), block_number, block_hash, ) msg = "all unlocks have been done, channel must be cleared" assert iteration.new_state is None, msg