def test_mediated_transfer(iterations=ITERATIONS): identifier = 1 amount = 1 expiration = 1 secrethash = sha3(ADDRESS) lock = Lock(amount, expiration, secrethash) nonce = 1 token = ADDRESS balance = 1 recipient = ADDRESS locksroot = sha3(ADDRESS) target = ADDRESS initiator = ADDRESS msg = LockedTransfer( identifier, nonce, token, balance, recipient, locksroot, lock, target, initiator, fee=0, ) msg.sign(PRIVKEY, ADDRESS) run_timeit('MediatedTranfer', msg, iterations=iterations)
def test_receive_hashlocktransfer_unknown(raiden_network): app0 = raiden_network[0] # pylint: disable=unbalanced-tuple-unpacking token_manager0 = app0.raiden.managers_by_token_address.values()[0] other_key = PrivateKey(HASH2, ctx=GLOBAL_CTX, raw=True) other_address = privatekey_to_address(other_key.private_key) amount = 10 lock = Lock(amount, 1, HASH) refund_transfer = RefundTransfer(identifier=1, nonce=1, token=token_manager0.token_address, transferred_amount=amount, recipient=app0.raiden.address, locksroot=HASH, lock=lock) sign_and_send(refund_transfer, other_key, other_address, app0) transfer_timeout = TransferTimeout(HASH, HASH) sign_and_send(transfer_timeout, other_key, other_address, app0) secret = Secret(1, HASH, token_manager0.token_address) sign_and_send(secret, other_key, other_address, app0) secret_request = SecretRequest(1, HASH, 1) sign_and_send(secret_request, other_key, other_address, app0) reveal_secret = RevealSecret(HASH) sign_and_send(reveal_secret, other_key, other_address, app0) # Whenever processing of ConfirmTransfer is implemented test it here # too by removing the expectation of an exception with pytest.raises(KeyError): confirm_transfer = ConfirmTransfer(HASH) sign_and_send(confirm_transfer, other_key, other_address, app0)
def _(properties, defaults=None) -> LockedTransferSignedState: defaults = defaults or LOCKED_TRANSFER_SIGNED_STATE_DEFAULTS params = _properties_to_dict(properties, defaults) transfer_params = _properties_to_dict(params.pop('transfer'), defaults.transfer) balance_proof_params = _properties_to_dict( transfer_params.pop('balance_proof'), defaults.transfer.balance_proof, ) lock = Lock( amount=transfer_params.pop('amount'), expiration=transfer_params.pop('expiration'), secrethash=sha3(transfer_params.pop('secret')), ) pkey = params.pop('pkey') signer = LocalSigner(pkey) sender = params.pop('sender') params.update(transfer_params) params.update(balance_proof_params) params['token_network_address'] = params.pop('token_network_identifier') if params['locksroot'] == EMPTY_MERKLE_ROOT: params['locksroot'] = lock.lockhash locked_transfer = LockedTransfer(lock=lock, **params) locked_transfer.sign(signer) assert locked_transfer.sender == sender return lockedtransfersigned_from_message(locked_transfer)
def test_mediated_transfer(iterations=ITERATIONS): amount = 1 expiration = 1 hashlock = sha3(ADDRESS) lock = Lock(amount, expiration, hashlock) nonce = 1 asset = ADDRESS balance = 1 recipient = ADDRESS locksroot = sha3(ADDRESS) target = ADDRESS initiator = ADDRESS msg = MediatedTransfer(nonce, asset, balance, recipient, locksroot, lock, target, initiator, fee=0) msg.sign(PRIVKEY) run_timeit('MediatedTranfer', msg, iterations=iterations)
def unlock(self, ctx, locked_encoded, merkleproof_encoded, secret): if self.settled is not 0: raise RuntimeError('Contract is settled.') if self.closed is 0: raise RuntimeError('Contract is open.') if ctx['msg.sender'] not in self.participants: raise ValueError('Unknow address.') partner = self.partner(ctx['msg.sender']) state = self.participants[partner] transfer = state.transfer # if partner haven't made a single transfer if transfer is None: return merkle_proof = tuple32(merkleproof_encoded) lock = Lock.from_bytes(locked_encoded) hashlock = lock.hashlock if hashlock != sha3(secret): raise ValueError('Invalid secret') is_valid_proof = check_proof( merkle_proof, transfer.locksroot, sha3(lock.as_bytes), ) if not is_valid_proof: raise ValueError('Invalid merkle proof') transfer.append(lock)
def test_receive_hashlocktransfer_unknown(raiden_network): app0 = raiden_network[0] # pylint: disable=unbalanced-tuple-unpacking token_manager0 = app0.raiden.managers_by_token_address.values()[0] other_key = PrivateKey(HASH2, ctx=GLOBAL_CTX, raw=True) other_address = privatekey_to_address(other_key.private_key) amount = 10 lock = Lock(amount, 1, HASH) refund_transfer = RefundTransfer(identifier=1, nonce=1, token=token_manager0.token_address, transferred_amount=amount, recipient=app0.raiden.address, locksroot=HASH, lock=lock) sign_and_send(refund_transfer, other_key, other_address, app0) secret = Secret(1, HASH, token_manager0.token_address) sign_and_send(secret, other_key, other_address, app0) secret_request = SecretRequest(1, HASH, 1) sign_and_send(secret_request, other_key, other_address, app0) reveal_secret = RevealSecret(HASH) sign_and_send(reveal_secret, other_key, other_address, app0)
def test_withdraw_twice(tester_registry_address, reveal_timeout, tester_channels, tester_chain): """ A lock can be withdrawn only once, the second try must fail. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] pseudo_random_generator = random.Random() lock_expiration = tester_chain.block.number + reveal_timeout + 5 secret = b'secretsecretsecretsecretsecretse' new_block = Block(tester_chain.block.number) channel.state_transition( channel0, new_block, pseudo_random_generator, new_block.block_number, ) channel.state_transition( channel1, new_block, pseudo_random_generator, new_block.block_number, ) lock = Lock(17, lock_expiration, sha3(secret)) mediated0 = make_mediated_transfer( tester_registry_address, channel1, channel0, privatekey_to_address(pkey1), privatekey_to_address(pkey0), lock, pkey1, secret, ) mediated0_hash = sha3(mediated0.packed().data[:-65]) nettingchannel.close( mediated0.nonce, mediated0.transferred_amount, mediated0.locksroot, mediated0_hash, mediated0.signature, sender=pkey0, ) unlock_proofs = channel.get_known_unlocks(channel0.partner_state) proof = unlock_proofs[0] nettingchannel.withdraw( proof.lock_encoded, b''.join(proof.merkle_proof), proof.secret, sender=pkey0, ) with pytest.raises(TransactionFailed): nettingchannel.withdraw( proof.lock_encoded, b''.join(proof.merkle_proof), proof.secret, sender=pkey0, )
def make_signed_transfer_from_counter(counter): lock = Lock( amount=next(counter), expiration=next(counter), secrethash=sha3(factories.make_secret(next(counter))), ) signed_transfer = factories.make_signed_transfer_state( amount=next(counter), initiator=factories.make_address(), target=factories.make_address(), expiration=next(counter), secret=factories.make_secret(next(counter)), payment_identifier=next(counter), message_identifier=next(counter), nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), locksroot=sha3(lock.as_bytes), recipient=factories.make_address(), channel_identifier=next(counter), token_network_address=factories.make_address(), token=factories.make_address(), pkey=factories.HOP1_KEY, sender=factories.HOP1, ) return signed_transfer
def unlock(self, ctx, locked_encoded, merkleproof_encoded, secret): if self.settled is not None: raise RuntimeError('Contract is settled.') if self.closed is None: raise RuntimeError('Contract is open.') if ctx['msg.sender'] not in self.participants: raise ValueError('Unknow address.') partner = self.partner(ctx['msg.sender']) state = self.participants[partner] transfer = state.transfer # if partner haven't made a single transfer if transfer is None: return merkle_proof = tuple32(merkleproof_encoded) lock = Lock.from_bytes(locked_encoded) hashlock = lock.hashlock if hashlock != sha3(secret): raise ValueError('Invalid secret') is_valid_proof = check_proof( merkle_proof, transfer.locksroot, sha3(transfer.lock.as_bytes), ) if not is_valid_proof: raise ValueError('Invalid merkle proof') transfer.append(lock)
def _update_balance_proof_data(self, partner, amount, expiration, secret): expected = self._get_balance_proof_data(partner) lock = Lock(amount=amount, expiration=expiration, secrethash=sha3(secret)) expected.update(amount, lock.lockhash) return expected
def test_receive_hashlocktransfer_unknown(raiden_network): app0 = raiden_network[0] # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] other_key = PrivateKey(HASH2) other_address = privatekey_to_address(HASH2) amount = 10 lock = Lock(amount, 1, HASH) refund_transfer = RefundTransfer( identifier=1, nonce=1, token=graph0.token_address, transferred_amount=amount, recipient=app0.raiden.address, locksroot=HASH, lock=lock ) sign_and_send(refund_transfer, other_key, other_address, app0) secret = Secret(1, HASH, graph0.token_address) sign_and_send(secret, other_key, other_address, app0) secret_request = SecretRequest(1, HASH, 1) sign_and_send(secret_request, other_key, other_address, app0) reveal_secret = RevealSecret(HASH) sign_and_send(reveal_secret, other_key, other_address, app0)
def test_decode_refund_transfer(settle_timeout, tester_state, tester_token): privatekey0 = tester.DEFAULT_KEY privatekey1 = tester.k1 address0 = privatekey_to_address(privatekey0) address1 = privatekey_to_address(privatekey1) dtester = deploy_decoder_tester(tester_state, tester_token.address, address0, address1, settle_timeout) locksroot = sha3('Mainz') amount = 1337 expiration = 19 lock = Lock(amount, expiration, locksroot) message = RefundTransfer(identifier=321313, nonce=4242452, token=tester_token.address, transferred_amount=amount, recipient=address1, locksroot=locksroot, lock=lock) message.sign(PrivateKey(privatekey0, ctx=GLOBAL_CTX, raw=True), address0) _, publickey = wrap_and_validate(message.encode()) recovered_address = address_from_key(publickey) assert recovered_address == address0 assert dtester.testDecodeTransfer(message.encode(), sender=privatekey1) is True assert dtester.decodedNonce() == 4242452 assert dtester.decodedToken() == tester_token.address.encode('hex') assert dtester.decodedLocksroot() == locksroot
def _(properties, defaults=None) -> LockedTransferSignedState: transfer: LockedTransferSignedStateProperties = create_properties( properties, defaults) params = {key: value for key, value in transfer.__dict__.items()} lock = Lock(amount=transfer.amount, expiration=transfer.expiration, secrethash=sha3(transfer.secret)) pkey = params.pop("pkey") signer = LocalSigner(pkey) sender = params.pop("sender") canonical_identifier = params.pop("canonical_identifier") params["chain_id"] = int(canonical_identifier.chain_identifier) params["channel_identifier"] = int(canonical_identifier.channel_identifier) params[ "token_network_address"] = canonical_identifier.token_network_address if params["locksroot"] == EMPTY_MERKLE_ROOT: params["locksroot"] = lock.lockhash locked_transfer = LockedTransfer(lock=lock, **params) locked_transfer.sign(signer) assert locked_transfer.sender == sender return lockedtransfersigned_from_message(locked_transfer)
def test_receive_lockedtransfer_invalidnonce( raiden_network, deposit, token_addresses, reveal_timeout, network_wait ): app0, app1, app2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) amount = 10 mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait, ) amount = 10 payment_identifier = 1 repeated_nonce = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=repeated_nonce, token_network_address=token_network_identifier, token=token_address, channel=channel0.identifier, transferred_amount=amount, locked_amount=amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(amount, expiration, UNIT_SECRETHASH), target=app2.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], )
def run_test_receive_lockedtransfer_invalidnonce(raiden_network, number_of_nodes, deposit, token_addresses, reveal_timeout, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address) channel0 = get_channelstate(app0, app1, token_network_identifier) amount = 10 transfer( initiator_app=app0, target_app=app2, token_address=token_address, amount=amount, identifier=1, timeout=network_wait * number_of_nodes, ) amount = 10 payment_identifier = 1 repeated_nonce = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=repeated_nonce, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=amount, locked_amount=amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(amount=amount, expiration=expiration, secrethash=UNIT_SECRETHASH), target=app2.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1) with gevent.Timeout(network_wait): wait_assert( assert_synced_channel_state, token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_settle_with_locked_mediated_transfer_for_counterparty( deposit, settle_timeout, reveal_timeout, tester_chain, tester_channels, tester_token): """ Test settle with a locked mediated transfer for the counter party. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] payment_network_identifier = factories.make_address() address0 = privatekey_to_address(pkey0) address1 = privatekey_to_address(pkey1) initial0 = tester_token.balanceOf(address0, sender=pkey0) initial1 = tester_token.balanceOf(address1, sender=pkey0) transferred_amount0 = 30 increase_transferred_amount( payment_network_identifier, channel0, channel1, transferred_amount0, pkey0, ) expiration0 = tester_chain.block.number + reveal_timeout + 5 new_block = Block(tester_chain.block.number) channel.state_transition(channel0, new_block, new_block.block_number) channel.state_transition(channel1, new_block, new_block.block_number) lock0 = Lock(amount=29, expiration=expiration0, secrethash=sha3(b'lock1')) mediated0 = make_mediated_transfer( channel0, channel1, address0, address1, lock0, pkey0, ) nettingchannel.close(sender=pkey0) mediated0_hash = sha3(mediated0.packed().data[:-65]) nettingchannel.updateTransfer( mediated0.nonce, mediated0.transferred_amount, mediated0.locksroot, mediated0_hash, mediated0.signature, sender=pkey1, ) tester_chain.mine(number_of_blocks=settle_timeout + 1) nettingchannel.settle(sender=pkey1) # the balances only change by transferred_amount because the lock was /not/ unlocked balance0 = initial0 + deposit - transferred_amount0 balance1 = initial1 + transferred_amount0 assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0 assert tester_token.balanceOf(address0, sender=pkey0) == balance0 assert tester_token.balanceOf(address1, sender=pkey0) == balance1
def create_lockedtransfer(self, amount, expiration, hashlock): """ Return a LockedTransfer message. This message needs to be signed and registered with the channel before sent. """ if not self.isopen: raise ValueError('The channel is closed') block_number = self.external_state.get_block_number() # expiration is not sufficient for guarantee settling if expiration - block_number >= self.settle_timeout: log.debug( "Transfer expiration doesn't allow for corret settlement.", expiration=expiration, block_number=block_number, settle_timeout=self.settle_timeout, ) raise ValueError('Invalid expiration') if expiration - self.reveal_timeout < block_number: log.debug( 'Expiration smaller than the minimum requried.', expiration=expiration, block_number=block_number, reveal_timeout=self.reveal_timeout, ) raise ValueError('Invalid expiration') from_ = self.our_state to_ = self.partner_state distributable = from_.distributable(to_) if amount <= 0 or amount > distributable: log.debug( 'Insufficient funds', amount=amount, distributable=distributable, ) raise ValueError('Insufficient funds') lock = Lock(amount, expiration, hashlock) # start of critical read section transfered_amount = from_.transfered_amount updated_locksroot = to_.locked.root_with(lock) # end of critical read section return LockedTransfer( nonce=from_.nonce, asset=self.asset_address, transfered_amount=transfered_amount, recipient=to_.address, locksroot=updated_locksroot, lock=lock, )
def test_mediated_transfer(): nonce = balance = 1 asset = recipient = target = initiator = address hashlock = locksroot = sha3(address) amount = expiration = 1 lock = Lock(amount, expiration, hashlock) d = lock.encode() assert Lock.decode(d) == lock msg = MediatedTransfer(nonce, asset, balance, recipient, locksroot, lock, target, initiator, fee=0) msg.sign(privkey) dm = msg.encode() msg2 = decode(dm) assert msg2 == msg assert msg2.lock == lock
def make_signed_transfer( amount, initiator, target, expiration, secret, payment_identifier=1, message_identifier=None, nonce=1, transferred_amount=0, locked_amount=None, locksroot=EMPTY_MERKLE_ROOT, recipient=UNIT_TRANSFER_TARGET, channel_identifier=UNIT_CHANNEL_ID, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, token=UNIT_TOKEN_ADDRESS, pkey=UNIT_TRANSFER_PKEY, sender=UNIT_TRANSFER_SENDER, ): if message_identifier is None: message_identifier = random.randint(0, UINT64_MAX) secrethash = sha3(secret) lock = Lock( amount, expiration, secrethash, ) if locksroot == EMPTY_MERKLE_ROOT: locksroot = sha3(lock.as_bytes) if locked_amount is None: locked_amount = amount else: assert locked_amount >= amount transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=payment_identifier, nonce=nonce, token_network_address=token_network_address, token=token, channel_identifier=channel_identifier, transferred_amount=transferred_amount, locked_amount=locked_amount, recipient=recipient, locksroot=locksroot, lock=lock, target=target, initiator=initiator, ) transfer.sign(pkey) assert transfer.sender == sender return lockedtransfersigned_from_message(transfer)
def test_received_lockedtransfer_closedchannel(raiden_network, reveal_timeout, token_addresses, deposit): app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] channel0 = get_channelstate(app0, app1, token_address) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one mediated transfer for the closed channel lock_amount = 10 payment_identifier = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, registry_address=app0.raiden.default_registry.address, token=token_address, channel=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synched_channel_state( token_address, app0, deposit, [], app1, deposit, [], )
def test_unlock(deposit, settle_timeout, reveal_timeout, tester_channels, tester_state, tester_token): pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] address0 = privatekey_to_address(pkey0) address1 = privatekey_to_address(pkey1) initial_balance0 = tester_token.balanceOf(address0, sender=pkey0) initial_balance1 = tester_token.balanceOf(address1, sender=pkey0) lock_amount = 31 lock_expiration = tester_state.block.number + reveal_timeout + 5 secret = 'secretsecretsecretsecretsecretse' hashlock = sha3(secret) new_block = Block(tester_state.block.number) channel0.state_transition(new_block) channel1.state_transition(new_block) lock0 = Lock(lock_amount, lock_expiration, hashlock) mediated0 = make_mediated_transfer( channel0, channel1, address0, address1, lock0, pkey0, tester_state.block.number, secret, ) mediated0_data = str(mediated0.packed().data) proof = channel1.our_state.balance_proof.compute_proof_for_lock( secret, mediated0.lock, ) nettingchannel.close(mediated0_data, sender=pkey1) tester_state.mine(number_of_blocks=1) nettingchannel.unlock( proof.lock_encoded, ''.join(proof.merkle_proof), proof.secret, sender=pkey1, ) tester_state.mine(number_of_blocks=settle_timeout + 1) nettingchannel.settle(sender=pkey0) balance0 = initial_balance0 + deposit - lock0.amount balance1 = initial_balance1 + deposit + lock0.amount assert tester_token.balanceOf(address0, sender=pkey0) == balance0 assert tester_token.balanceOf(address1, sender=pkey0) == balance1 assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
def test_withdraw_expired_lock(reveal_timeout, tester_channels, tester_chain): pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] pseudo_random_generator = random.Random() lock_timeout = reveal_timeout + 5 lock_expiration = tester_chain.block.number + lock_timeout secret = b'expiredlockexpiredlockexpiredloc' secrethash = sha3(secret) new_block = Block(tester_chain.block.number) channel.state_transition( channel0, new_block, pseudo_random_generator, new_block.block_number, ) channel.state_transition( channel1, new_block, pseudo_random_generator, new_block.block_number, ) lock1 = Lock(amount=31, expiration=lock_expiration, secrethash=secrethash) mediated0 = make_mediated_transfer( channel1, channel0, privatekey_to_address(pkey0), privatekey_to_address(pkey1), lock1, pkey1, secret, ) mediated0_hash = sha3(mediated0.packed().data[:-65]) nettingchannel.close( mediated0.nonce, mediated0.transferred_amount, mediated0.locksroot, mediated0_hash, mediated0.signature, sender=pkey0, ) # expire the lock tester_chain.mine(number_of_blocks=lock_timeout + 1) unlock_proofs = channel.get_known_unlocks(channel0.partner_state) proof = unlock_proofs[0] with pytest.raises(TransactionFailed): nettingchannel.withdraw( proof.lock_encoded, b''.join(proof.merkle_proof), proof.secret, sender=pkey0, )
def test_receive_lockedtransfer_invalidrecipient( raiden_network, token_addresses, reveal_timeout, deposit, ): app0, app1 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) payment_identifier = 1 invalid_recipient = make_address() lock_amount = 10 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=invalid_recipient, locksroot=UNIT_SECRETHASH, lock=Lock(amount=lock_amount, expiration=expiration, secrethash=UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.signer, app1, ) assert_synced_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def make_signed_transfer( amount, initiator, target, expiration, secret, payment_identifier=1, message_identifier=None, nonce=1, transferred_amount=0, locked_amount=None, recipient=UNIT_TRANSFER_TARGET, channel_identifier=UNIT_CHANNEL_ADDRESS, token=UNIT_TOKEN_ADDRESS, pkey=UNIT_TRANSFER_PKEY, sender=UNIT_TRANSFER_SENDER, ): if message_identifier is None: message_identifier = random.randint(0, UINT64_MAX) secrethash = sha3(secret) lock = Lock( amount, expiration, secrethash, ) if locked_amount is None: locked_amount = amount else: assert locked_amount >= amount transfer = LockedTransfer( message_identifier, payment_identifier, nonce, UNIT_REGISTRY_IDENTIFIER, token, channel_identifier, transferred_amount, locked_amount, recipient, lock.lockhash, lock, target, initiator, ) transfer.sign(pkey) assert transfer.sender == sender return lockedtransfersigned_from_message(transfer)
def test_mediated_after_direct_transfer(reveal_timeout, settle_timeout, deposit, tester_state, tester_channels, tester_token): """ The transfer types must not change the behavior of the dispute. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] address0 = privatekey_to_address(pkey0) address1 = privatekey_to_address(pkey1) initial_balance0 = tester_token.balanceOf(address0, sender=pkey0) initial_balance1 = tester_token.balanceOf(address1, sender=pkey0) first_amount0 = 90 block_number = tester_state.block.number make_direct_transfer_from_channel( block_number, channel0, channel1, first_amount0, pkey0, ) lock_expiration = tester_state.block.number + reveal_timeout + 5 new_block = Block(tester_state.block.number) channel0.state_transition(new_block) channel1.state_transition(new_block) lock1 = Lock(amount=31, expiration=lock_expiration, hashlock=sha3('lock2')) second_mediated0 = make_mediated_transfer( channel0, channel1, address0, address1, lock1, pkey0, tester_state.block.number, ) second_mediated0_data = str(second_mediated0.packed().data) nettingchannel.close('', sender=pkey0) nettingchannel.updateTransfer(second_mediated0_data, sender=pkey1) tester_state.mine(number_of_blocks=settle_timeout + 1) nettingchannel.settle(sender=pkey0) # the balances only change by transferred_amount because the lock was /not/ unlocked balance0 = initial_balance0 + deposit - first_amount0 balance1 = initial_balance1 + deposit + first_amount0 assert tester_token.balanceOf(nettingchannel.address, sender=pkey1) == 0 assert tester_token.balanceOf(address0, sender=pkey0) == balance0 assert tester_token.balanceOf(address1, sender=pkey1) == balance1
def test_receive_lockedtransfer_invalidsender( raiden_network, token_addresses, deposit, reveal_timeout, ): app0, app1 = raiden_network token_address = token_addresses[0] other_key, other_address = make_privkey_address() token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) lock_amount = 10 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app0.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app0.raiden.address, initiator=other_address, fee=0, ) sign_and_inject( mediated_transfer_message, other_key, other_address, app0, ) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_receive_mediatedtransfer_invalidnonce(raiden_network, deposit, token_addresses, reveal_timeout, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] channel0 = get_channelstate(app0, app1, token_address) amount = 10 mediated_transfer( app0, app2, token_address, amount, timeout=network_wait, ) amount = 10 identifier = 1 repeated_nonce = 1 expiration = reveal_timeout * 2 mediated_transfer_message = MediatedTransfer( identifier=identifier, nonce=repeated_nonce, token=token_address, channel=channel0.identifier, transferred_amount=amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(amount, expiration, UNIT_SECRETHASH), target=app2.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def create_lockedtransfer(self, block_number, amount, identifier, expiration, hashlock): """ Return a LockedTransfer message. This message needs to be signed and registered with the channel before sent. """ timeout = expiration - block_number if not self.can_transfer: raise ValueError( 'Transfer not possible, no funding or channel closed.') # the expiration cannot be lower than the reveal timeout (otherwise we # dont have enough time to listen for the ChannelSecretRevealed event) if timeout <= self.reveal_timeout: log.debug( 'Lock expiration is lower than reveal timeout.', expiration=expiration, block_number=self.block_number, reveal_timeout=self.reveal_timeout, ) raise ValueError('Invalid expiration.') from_ = self.our_state to_ = self.partner_state distributable = from_.distributable(to_) if amount <= 0 or amount > distributable: log.debug( 'Insufficient funds', amount=amount, distributable=distributable, ) raise ValueError('Insufficient funds') lock = Lock(amount, expiration, hashlock) updated_locksroot = to_.compute_merkleroot_with(include=lock) transferred_amount = from_.transferred_amount return LockedTransfer( identifier=identifier, nonce=from_.nonce, token=self.token_address, transferred_amount=transferred_amount, recipient=to_.address, locksroot=updated_locksroot, lock=lock, )
def test_settle_with_locked_mediated_transfer_for_counterparty( deposit, settle_timeout, reveal_timeout, tester_state, tester_channels, tester_token): """ Test settle with a locked mediated transfer for the counter party. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] address0 = privatekey_to_address(pkey0) address1 = privatekey_to_address(pkey1) initial0 = tester_token.balanceOf(address0, sender=pkey0) initial1 = tester_token.balanceOf(address1, sender=pkey0) transferred_amount0 = 30 increase_transferred_amount(channel0, channel1, transferred_amount0) expiration0 = tester_state.block.number + reveal_timeout + 5 new_block = Block(tester_state.block.number) channel0.state_transition(new_block) channel1.state_transition(new_block) lock0 = Lock(amount=29, expiration=expiration0, hashlock=sha3('lock1')) mediated = make_mediated_transfer( channel0, channel1, address0, address1, lock0, pkey0, tester_state.block.number, ) nettingchannel.close('', sender=pkey0) transfer_data = str(mediated.packed().data) nettingchannel.updateTransfer(transfer_data, sender=pkey1) tester_state.mine(number_of_blocks=settle_timeout + 1) nettingchannel.settle(sender=pkey1) # the balances only change by transferred_amount because the lock was /not/ unlocked balance0 = initial0 + deposit - transferred_amount0 balance1 = initial1 + transferred_amount0 assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0 assert tester_token.balanceOf(address0, sender=pkey0) == balance0 assert tester_token.balanceOf(address1, sender=pkey0) == balance1
def handle_contract_send_channelunlock( raiden: RaidenService, channel_unlock_event: ContractSendChannelBatchUnlock, ): channel = raiden.chain.netting_channel(channel_unlock_event.channel_identifier) block_number = raiden.get_block_number() for unlock_proof in channel_unlock_event.unlock_proofs: lock = Lock.from_bytes(unlock_proof.lock_encoded) if lock.expiration < block_number: log.error('Lock has expired!', lock=lock) else: channel.unlock(unlock_proof)
def test_locked_transfer(iterations=ITERATIONS): amount = 1 expiration = 1 hashlock = sha3(ADDRESS) lock = Lock(amount, expiration, hashlock) nonce = 1 asset = ADDRESS balance = 1 recipient = ADDRESS locksroot = sha3(ADDRESS) msg = LockedTransfer(nonce, asset, balance, recipient, locksroot, lock) msg.sign(PRIVKEY) run_timeit('LockedTransfer', msg, iterations=iterations)
def handle_contract_channelwithdraw( raiden: 'RaidenService', channel_withdraw_event: ContractSendChannelWithdraw): channel = raiden.chain.netting_channel( channel_withdraw_event.channel_identifier) block_number = raiden.get_block_number() for unlock_proof in channel_withdraw_event.unlock_proofs: lock = Lock.from_bytes(unlock_proof.lock_encoded) if lock.expiration < block_number: log.error('Lock has expired!', lock=lock) else: channel.withdraw(unlock_proof)
def close(self, ctx, sender, transfers_encoded, locked_encoded, # noqa merkleproof_encoded, secret): """" Request the closing of the channel. Can be called multiple times. lock period starts with first valid call. Args: sender (address): The sender address. transfers_encoded (List[transfer]): A list of maximum length of 2 containing the transfer encoded using the fixed length format, may be empty. ctx: Block chain state used for mocking. locked_encoded (bin): The Lock to be unlocked. merkleproof_encoded (bin): A proof that the given lock is contained in the latest transfer. The binary data is composed of a single hash at every 4bytes. secret (bin): The secret that unlocks the lock `hashlock = sha3(secret)`. Todo: if challenged, keep track of who provided the last valid answer, punish the wrongdoer here, check that participants only updates their own balance are counted, because they could sign something for the other party to blame it. """ # pylint: disable=too-many-arguments,too-many-locals,too-many-branches # if len(transfers_encoded): # raise ValueError('transfers_encoded needs at least 1 item.') if len(transfers_encoded) > 2: raise ValueError('transfers_encoded cannot have more than 2 items.') if self.settled: raise RuntimeError('contract is settled') # the merkleproof can be empty, if there is only one haslock has_oneofunlocked = locked_encoded or secret has_allofunlocked = locked_encoded and secret if has_oneofunlocked and not has_allofunlocked: raise ValueError( 'all arguments `merkle_proof`, `locked`, and `secret` must be provided' ) last_sent_transfers = [] for data in transfers_encoded: if data[0] == DIRECTTRANSFER: last_sent_transfers.append( DirectTransfer.decode(data) ) elif data[0] == MEDIATEDTRANSFER: last_sent_transfers.append( MediatedTransfer.decode(data) ) elif data[0] == CANCELTRANSFER: last_sent_transfers.append( CancelTransfer.decode(data) ) # convinience for testing only (LockedTransfer are not exchanged between nodes) elif data[0] == LOCKEDTRANSFER: last_sent_transfers.append( LockedTransfer.decode(data) ) else: raise ValueError('invalid transfer type {}'.format(type(data[0]))) # keep the latest claim for transfer in last_sent_transfers: if transfer.sender not in self.participants: raise ValueError('Invalid tansfer, sender is not a participant') sender_state = self.participants[transfer.sender] if is_newer_transfer(transfer, sender_state): sender_state['last_sent_transfer'] = transfer partner = self.partner(sender) partner_state = self.participants[partner] if last_sent_transfers: transfer = last_sent_transfers[-1] # XXX: check me # register un-locked if merkleproof_encoded: merkle_proof = tuple32(merkleproof_encoded) lock = Lock.from_bytes(locked_encoded) hashlock = lock.hashlock if hashlock != sha3(secret): raise ValueError('invalid secret') # the partner might not have made a transfer if partner_state['last_sent_transfer'] is not None: assert check_proof( merkle_proof, partner_state['last_sent_transfer'].locksroot, sha3(transfer.lock.as_bytes), ) partner_state['unlocked'].append(lock) if self.closed is None: log.debug('closing contract', netcontract_address=pex(self.netcontract_address)) self.closed = ctx['block_number']