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 update(self, amount, lock): self._pending_locks = channel.compute_locks_with(self._pending_locks, lock) if self.properties: self.properties = factories.replace( self.properties, locked_amount=self.properties.locked_amount + amount, locksroot=compute_locksroot(self._pending_locks), nonce=self.properties.nonce + 1, ) else: self.properties = factories.BalanceProofProperties( transferred_amount=0, locked_amount=amount, nonce=1, locksroot=compute_locksroot(self._pending_locks), canonical_identifier=self._canonical_identifier, )
def make_receive_expired_lock( channel_state: NettingChannelState, privkey: bytes, nonce: Nonce, transferred_amount: TokenAmount, lock: HashTimeLockState, locked_amount: LockedAmount, pending_locks: PendingLocksState = None, chain_id: ChainID = None, ) -> ReceiveLockExpired: typecheck(lock, HashTimeLockState) signer = LocalSigner(privkey) address = signer.address if address not in (channel_state.our_state.address, channel_state.partner_state.address): raise ValueError("Private key does not match any of the participants.") if pending_locks is None: pending_locks = make_empty_pending_locks_state() else: assert lock.encoded not in pending_locks.locks locksroot = compute_locksroot(pending_locks) chain_id = chain_id or channel_state.chain_id lock_expired_msg = LockExpired( chain_id=chain_id, nonce=nonce, message_identifier=make_message_identifier(), transferred_amount=transferred_amount, locked_amount=TokenAmount(locked_amount), locksroot=locksroot, channel_identifier=channel_state.identifier, token_network_address=channel_state.token_network_address, recipient=channel_state.partner_state.address, secrethash=lock.secrethash, signature=EMPTY_SIGNATURE, ) lock_expired_msg.sign(signer) balance_proof = balanceproof_from_envelope(lock_expired_msg) receive_lockedtransfer = ReceiveLockExpired( balance_proof=balance_proof, secrethash=lock.secrethash, message_identifier=make_message_identifier(), sender=balance_proof.sender, ) return receive_lockedtransfer
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 make_receive_transfer_mediated( channel_state: NettingChannelState, privkey: bytes, nonce: Nonce, transferred_amount: TokenAmount, lock: HashTimeLockState, pending_locks: PendingLocksState = None, locked_amount: Optional[PaymentWithFeeAmount] = None, chain_id: Optional[ChainID] = None, ) -> LockedTransferSignedState: typecheck(lock, HashTimeLockState) signer = LocalSigner(privkey) address = signer.address if address not in (channel_state.our_state.address, channel_state.partner_state.address): raise ValueError("Private key does not match any of the participants.") if pending_locks is None: locks = make_empty_pending_locks_state() locks.locks.append(lock.encoded) else: assert bytes(lock.encoded) in pending_locks.locks locks = pending_locks if locked_amount is None: locked_amount = lock.amount assert locked_amount >= lock.amount locksroot = compute_locksroot(locks) payment_identifier = PaymentID(nonce) transfer_target = make_target_address() transfer_initiator = make_initiator_address() chain_id = chain_id or channel_state.chain_id transfer_metadata = Metadata(routes=[ RouteMetadata( route=[channel_state.our_state.address, Address(transfer_target)]) ]) mediated_transfer_msg = LockedTransfer( chain_id=chain_id, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=nonce, token_network_address=channel_state.token_network_address, token=channel_state.token_address, channel_identifier=channel_state.identifier, transferred_amount=transferred_amount, locked_amount=TokenAmount(locked_amount), recipient=channel_state.partner_state.address, locksroot=locksroot, lock=Lock(amount=lock.amount, expiration=lock.expiration, secrethash=lock.secrethash), target=transfer_target, initiator=transfer_initiator, signature=EMPTY_SIGNATURE, fee=0, metadata=transfer_metadata, ) mediated_transfer_msg.sign(signer) receive_lockedtransfer = LockedTransferSignedState( payment_identifier=payment_identifier, token=channel_state.token_address, lock=lock, initiator=transfer_initiator, target=transfer_target, message_identifier=make_message_identifier(), balance_proof=balanceproof_from_envelope(mediated_transfer_msg), routes=[ route_metadata.route for route_metadata in transfer_metadata.routes ], ) return receive_lockedtransfer
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_empty(): locks = PendingLocksState(list()) assert compute_locksroot(locks) == LOCKSROOT_OF_NO_LOCKS