def handle_message_crosslockedtransfer(raiden: RaidenService, message: CrossLockedTransfer): locked_transfer_message = LockedTransfer( message.chain_id, message.message_identifier, message.payment_identifier, message.nonce, message.token_network_address, message.token, message.channel, message.transferred_amount, message.locked_amount, message.recipient, message.locksroot, message.lock, message.target, message.initiator, message.fee) #locked_transfer_message.sender = message.sender locked_transfer_message.signature = message.locked_transfer_signature if message.target == raiden.address: raiden.cross_handle_recieved_locked_transfer(locked_transfer_message, message.cross_id) raiden.wal.change_crosstransaction_status(message.cross_id, 4) raiden.wal.storage.change_crosstransaction_r( message.cross_id, encode_hex(locked_transfer_message.lock.secrethash), "") #to do send lnd string to lnd lnd_string = message.lnd_string.decode('utf-8') raiden.send_payment_request(lnd_string) else: handle_message_lockedtransfer(raiden, locked_transfer_message)
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 pending_mediated_transfer(app_chain, token_network_identifier, amount, identifier): """ Nice to read shortcut to make a LockedTransfer where the secret is _not_ revealed. While the secret is not revealed all apps will be synchronized, meaning they are all going to receive the LockedTransfer message. Returns: The secret used to generate the LockedTransfer """ # pylint: disable=too-many-locals if len(app_chain) < 2: raise ValueError('Cannot make a LockedTransfer with less than two apps') target = app_chain[-1].raiden.address # Generate a secret initiator_channel = views.get_channelstate_by_token_network_and_partner( views.state_from_app(app_chain[0]), token_network_identifier, app_chain[1].raiden.address, ) address = initiator_channel.identifier nonce_int = channel.get_next_nonce(initiator_channel.our_state) nonce_bytes = nonce_int.to_bytes(2, 'big') secret = sha3(address + nonce_bytes) initiator_app = app_chain[0] init_initiator_statechange = initiator_init( initiator_app.raiden, identifier, amount, secret, token_network_identifier, target, ) events = initiator_app.raiden.wal.log_and_dispatch( init_initiator_statechange, initiator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) initiator_app.raiden.sign(transfermessage) for mediator_app in app_chain[1:-1]: mediator_init_statechange = mediator_init(mediator_app.raiden, transfermessage) events = mediator_app.raiden.wal.log_and_dispatch( mediator_init_statechange, mediator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) mediator_app.raiden.sign(transfermessage) target_app = app_chain[-1] mediator_init_statechange = target_init(transfermessage) events = target_app.raiden.wal.log_and_dispatch( mediator_init_statechange, target_app.raiden.get_block_number(), ) return secret
def pending_mediated_transfer(app_chain, token, amount, identifier): """ Nice to read shortcut to make a LockedTransfer where the secret is _not_ revealed. While the secret is not revealed all apps will be synchronized, meaning they are all going to receive the LockedTransfer message. Returns: The secret used to generate the LockedTransfer """ # pylint: disable=too-many-locals if len(app_chain) < 2: raise ValueError( 'Cannot make a LockedTransfer with less than two apps') target = app_chain[-1].raiden.address # Generate a secret initiator_channel = get_channelstate(app_chain[0], app_chain[1], token) address = initiator_channel.identifier nonce_int = channel.get_next_nonce(initiator_channel.our_state) nonce_bytes = nonce_int.to_bytes(2, 'big') secret = sha3(address + nonce_bytes) initiator_app = app_chain[0] init_initiator_statechange = initiator_init( initiator_app.raiden, identifier, amount, secret, initiator_app.raiden.default_registry.address, token, target, ) events = initiator_app.raiden.wal.log_and_dispatch( init_initiator_statechange, initiator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) initiator_app.raiden.sign(transfermessage) for mediator_app in app_chain[1:-1]: mediator_init_statechange = mediator_init(mediator_app.raiden, transfermessage) events = mediator_app.raiden.wal.log_and_dispatch( mediator_init_statechange, mediator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) mediator_app.raiden.sign(transfermessage) target_app = app_chain[-1] mediator_init_statechange = target_init(target_app.raiden, transfermessage) events = target_app.raiden.wal.log_and_dispatch( mediator_init_statechange, target_app.raiden.get_block_number(), ) return secret
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 _(properties, defaults=None) -> LockedTransfer: params, signer = prepare_locked_transfer(properties, defaults) transfer = LockedTransfer(**params) transfer.sign(signer) assert params["sender"] == transfer.sender return transfer
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 _(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') 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(pkey) assert locked_transfer.sender == sender return lockedtransfersigned_from_message(locked_transfer)
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 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=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=UNIT_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 make_receive_transfer_mediated( channel_state, privkey, nonce, transferred_amount, lock, merkletree_leaves=None): if not isinstance(lock, HashTimeLockState): raise ValueError('lock must be of type HashTimeLockState') address = privatekey_to_address(privkey.secret) 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 merkletree_leaves is None: layers = [[lock.lockhash]] else: assert lock.lockhash in merkletree_leaves layers = compute_layers(merkletree_leaves) locksroot = layers[MERKLEROOT][0] message_identifier = random.randint(0, UINT64_MAX) payment_identifier = nonce transfer_target = factories.make_address() transfer_initiator = factories.make_address() mediated_transfer_msg = LockedTransfer( message_identifier, payment_identifier, nonce, channel_state.token_address, channel_state.identifier, transferred_amount, channel_state.partner_state.address, locksroot, lock, transfer_target, transfer_initiator, ) mediated_transfer_msg.sign(privkey, address) balance_proof = balanceproof_from_envelope(mediated_transfer_msg) receive_lockedtransfer = LockedTransferSignedState( payment_identifier, channel_state.token_address, balance_proof, lock, transfer_initiator, transfer_target, ) return receive_lockedtransfer
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_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 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, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, 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_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 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_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 make_mediated_transfer(registry_address, from_channel, partner_channel, initiator, target, lock, pkey, secret=None): """ Helper to create and register a mediated transfer from `from_channel` to `partner_channel`.""" payment_identifier = channel.get_next_nonce(from_channel.our_state) message_identifier = random.randint(0, UINT64_MAX) lockedtransfer = channel.send_lockedtransfer( registry_address, from_channel, initiator, target, lock.amount, message_identifier, payment_identifier, lock.expiration, lock.secrethash, ) mediated_transfer_msg = LockedTransfer.from_event(lockedtransfer) address = privatekey_to_address(pkey) sign_key = PrivateKey(pkey) mediated_transfer_msg.sign(sign_key, address) # compute the signature balance_proof = balanceproof_from_envelope(mediated_transfer_msg) lockedtransfer.balance_proof = balance_proof # if this fails it's not the right key for the current `from_channel` assert mediated_transfer_msg.sender == from_channel.our_state.address receive_lockedtransfer = lockedtransfersigned_from_message( mediated_transfer_msg) channel.handle_receive_lockedtransfer( partner_channel, receive_lockedtransfer, ) if secret is not None: random_sender = make_address() from_secretreveal = ReceiveSecretReveal(secret, random_sender) channel.handle_receive_secretreveal(from_channel, from_secretreveal) partner_secretreveal = ReceiveSecretReveal(secret, random_sender) channel.handle_receive_secretreveal(partner_channel, partner_secretreveal) return mediated_transfer_msg
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 test_mediated_transfer_min_max(amount, payment_identifier, fee, nonce, transferred_amount): mediated_transfer = make_mediated_transfer( amount=amount, payment_identifier=payment_identifier, nonce=nonce, fee=fee, transferred_amount=transferred_amount, ) mediated_transfer.sign(signer) assert LockedTransfer.from_dict(mediated_transfer.to_dict()) == mediated_transfer
def test_mediated_transfer_min_max(amount, payment_identifier, fee, nonce, transferred_amount): mediated_transfer = make_mediated_transfer( amount=amount, payment_identifier=payment_identifier, nonce=nonce, fee=fee, transferred_amount=transferred_amount, ) mediated_transfer.sign(PRIVKEY) assert LockedTransfer.from_dict(mediated_transfer.to_dict()) == mediated_transfer
def test_mediated_transfer_min_max(amount, payment_identifier, fee, nonce, transferred_amount): mediated_transfer = factories.create( factories.LockedTransferProperties( amount=amount, payment_identifier=payment_identifier, nonce=nonce, fee=fee, transferred_amount=transferred_amount, ) ) assert LockedTransfer.from_dict(mediated_transfer.to_dict()) == mediated_transfer
def handle_send_lockedtransfer( raiden: 'RaidenService', send_mediated_transfer: SendLockedTransfer, ): mediated_transfer_message = LockedTransfer.from_event( send_mediated_transfer) raiden.sign(mediated_transfer_message) raiden.send_async( mediated_transfer_message.recipient, mediated_transfer_message, )
def decode_transfer(transfer_encoded): if transfer_encoded[0] == DIRECTTRANSFER: return DirectTransfer.decode(transfer_encoded) elif transfer_encoded[0] == MEDIATEDTRANSFER: return MediatedTransfer.decode(transfer_encoded) elif transfer_encoded[0] == REFUNDTRANSFER: return RefundTransfer.decode(transfer_encoded) # convinience for testing only (LockedTransfer are not exchanged between nodes) elif transfer_encoded[0] == LOCKEDTRANSFER: return LockedTransfer.decode(transfer_encoded) else: raise ValueError('invalid transfer type {}'.format(type(transfer_encoded[0])))
def target_init(transfer: LockedTransfer): from_transfer = lockedtransfersigned_from_message(transfer) print(transfer.to_dict()) from_route = RouteState( transfer.sender, from_transfer.balance_proof.channel_address, ) init_target_statechange = ActionInitTarget( from_route, from_transfer, ) return init_target_statechange
def decode_transfer(transfer_encoded): if transfer_encoded[0] == DIRECTTRANSFER: return DirectTransfer.decode(transfer_encoded) elif transfer_encoded[0] == MEDIATEDTRANSFER: return MediatedTransfer.decode(transfer_encoded) elif transfer_encoded[0] == CANCELTRANSFER: return CancelTransfer.decode(transfer_encoded) # convinience for testing only (LockedTransfer are not exchanged between nodes) elif transfer_encoded[0] == LOCKEDTRANSFER: return LockedTransfer.decode(transfer_encoded) else: raise ValueError('invalid transfer type {}'.format(type(transfer_encoded[0])))
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_mediated_transfer_min_max(amount, identifier, fee, nonce, transferred_amount): mediated_transfer = make_mediated_transfer( amount=amount, identifier=identifier, nonce=nonce, fee=fee, transferred_amount=transferred_amount, ) mediated_transfer.sign(PRIVKEY, ADDRESS) assert LockedTransfer.from_dict( mediated_transfer.to_dict()) == mediated_transfer
def make_mediated_transfer( message_identifier=None, payment_identifier=0, nonce=1, token_network_addresss=ADDRESS, token=ADDRESS, channel_identifier=UNIT_CHANNEL_ID, transferred_amount=0, locked_amount=None, amount=1, expiration=1, locksroot=EMPTY_MERKLE_ROOT, recipient=ADDRESS, target=ADDRESS, initiator=ADDRESS, fee=0, ): if message_identifier is None: message_identifier = random.randint(0, UINT64_MAX) lock = make_lock( amount=amount, expiration=expiration, ) if locksroot == EMPTY_MERKLE_ROOT: locksroot = sha3(lock.as_bytes) if locked_amount is None: locked_amount = amount else: assert locked_amount >= amount return LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=payment_identifier, nonce=nonce, token_network_address=token_network_addresss, token=token, channel_identifier=channel_identifier, transferred_amount=transferred_amount, locked_amount=locked_amount, recipient=recipient, locksroot=locksroot, lock=lock, target=target, initiator=initiator, fee=fee, )
def test_receive_lockedtransfer_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 = LockedTransfer( 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 make_signed_transfer( amount, initiator, target, expiration, secret, identifier=1, nonce=1, transferred_amount=0, recipient=UNIT_TRANSFER_TARGET, channel_identifier=UNIT_CHANNEL_ADDRESS, token=UNIT_TOKEN_ADDRESS, pkey=UNIT_TRANSFER_PKEY, sender=UNIT_TRANSFER_SENDER ): secrethash = sha3(secret) lock = Lock( amount, expiration, secrethash, ) transfer = LockedTransfer( identifier, nonce, token, channel_identifier, transferred_amount, recipient, lock.lockhash, lock, target, initiator, ) transfer.sign(pkey, sender) return lockedtransfersigned_from_message(transfer)
def make_mediated_transfer( from_channel, partner_channel, initiator, target, lock, pkey, secret=None, ): """ Helper to create and register a mediated transfer from `from_channel` to `partner_channel`.""" payment_identifier = channel.get_next_nonce(from_channel.our_state) message_identifier = random.randint(0, UINT64_MAX) lockedtransfer = channel.send_lockedtransfer( from_channel, initiator, target, lock.amount, message_identifier, payment_identifier, lock.expiration, lock.secrethash, ) mediated_transfer_msg = LockedTransfer.from_event(lockedtransfer) sign_key = PrivateKey(pkey) mediated_transfer_msg.sign(sign_key) # compute the signature balance_proof = balanceproof_from_envelope(mediated_transfer_msg) lockedtransfer.balance_proof = balance_proof # if this fails it's not the right key for the current `from_channel` assert mediated_transfer_msg.sender == from_channel.our_state.address receive_lockedtransfer = lockedtransfersigned_from_message(mediated_transfer_msg) channel.handle_receive_lockedtransfer( partner_channel, receive_lockedtransfer, ) if secret is not None: secrethash = sha3(secret) channel.register_secret(from_channel, secret, secrethash) channel.register_secret(partner_channel, secret, secrethash) return mediated_transfer_msg
def make_mediated_transfer( from_channel, partner_channel, initiator, target, lock, pkey, secret=None, ): """ Helper to create and register a mediated transfer from `from_channel` to `partner_channel`.""" payment_identifier = channel.get_next_nonce(from_channel.our_state) message_identifier = random.randint(0, UINT64_MAX) lockedtransfer = channel.send_lockedtransfer( from_channel, initiator, target, lock.amount, message_identifier, payment_identifier, lock.expiration, lock.secrethash, ) mediated_transfer_msg = LockedTransfer.from_event(lockedtransfer) sign_key = PrivateKey(pkey) mediated_transfer_msg.sign(sign_key, NETWORKNAME_TO_ID[TESTS]) # compute the signature balance_proof = balanceproof_from_envelope(mediated_transfer_msg) lockedtransfer.balance_proof = balance_proof # if this fails it's not the right key for the current `from_channel` assert mediated_transfer_msg.sender == from_channel.our_state.address receive_lockedtransfer = lockedtransfersigned_from_message(mediated_transfer_msg) channel.handle_receive_lockedtransfer( partner_channel, receive_lockedtransfer, ) if secret is not None: secrethash = sha3(secret) channel.register_secret(from_channel, secret, secrethash) channel.register_secret(partner_channel, secret, secrethash) return mediated_transfer_msg
def make_mediated_transfer(message_identifier=None, payment_identifier=0, nonce=1, registry_address=ADDRESS, token=ADDRESS, channel=ADDRESS, transferred_amount=0, locked_amount=None, amount=1, expiration=1, locksroot=EMPTY_MERKLE_ROOT, recipient=ADDRESS, target=ADDRESS, initiator=ADDRESS, fee=0): if message_identifier is None: message_identifier = random.randint(0, UINT64_MAX) lock = make_lock( amount=amount, expiration=expiration, ) if locksroot == EMPTY_MERKLE_ROOT: locksroot = sha3(lock.as_bytes) if locked_amount is None: locked_amount = amount else: assert locked_amount >= amount return LockedTransfer( message_identifier, payment_identifier, nonce, registry_address, token, channel, transferred_amount, locked_amount, recipient, locksroot, lock, target, initiator, fee, )
def run_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] 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) RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address) app0.raiden.chain.wait_until_block( target_block_number=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( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app1.raiden.address, 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) # The local state must not change since the channel is already closed assert_synced_channel_state(token_network_identifier, app0, deposit, [], app1, deposit, [])
def test_end_state(): token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() channel_address = make_address() balance1 = 70 balance2 = 110 lock_secret = sha3(b'test_end_state') lock_amount = 30 lock_expiration = 10 lock_hashlock = sha3(lock_secret) state1 = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) state2 = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.is_locked(lock_hashlock) is False assert state2.is_locked(lock_hashlock) is False assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT assert state1.nonce is None assert state2.nonce is None lock = Lock( lock_amount, lock_expiration, lock_hashlock, ) lock_hash = sha3(lock.as_bytes) transferred_amount = 0 locksroot = state2.compute_merkleroot_with(lock) locked_transfer = LockedTransfer( 1, nonce=1, token=token_address, channel=channel_address, transferred_amount=transferred_amount, recipient=state2.address, locksroot=locksroot, lock=lock, ) transfer_target = make_address() transfer_initiator = make_address() fee = 0 mediated_transfer = locked_transfer.to_mediatedtransfer( transfer_target, transfer_initiator, fee, ) mediated_transfer.sign(privkey1, address1) state1.register_locked_transfer(mediated_transfer) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount assert state2.distributable(state1) == balance2 assert state1.amount_locked == lock_amount assert state2.amount_locked == 0 assert state1.is_locked(lock_hashlock) is True assert state2.is_locked(lock_hashlock) is False assert merkleroot(state1.merkletree) == lock_hash assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT assert state1.nonce is 1 assert state2.nonce is None with pytest.raises(ValueError): state1.update_contract_balance(balance1 - 10) state1.update_contract_balance(balance1 + 10) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount + 10 assert state2.distributable(state1) == balance2 assert state1.amount_locked == lock_amount assert state2.amount_locked == 0 assert state1.is_locked(lock_hashlock) is True assert state2.is_locked(lock_hashlock) is False assert merkleroot(state1.merkletree) == lock_hash assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT assert state1.nonce is 1 assert state2.nonce is None # registering the secret should not change the locked amount state1.register_secret(lock_secret) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.is_locked(lock_hashlock) is False assert state2.is_locked(lock_hashlock) is False assert merkleroot(state1.merkletree) == lock_hash assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT assert state1.nonce is 1 assert state2.nonce is None secret_message = Secret( identifier=1, nonce=2, channel=channel_address, transferred_amount=transferred_amount + lock_amount, locksroot=EMPTY_MERKLE_ROOT, secret=lock_secret, ) secret_message.sign(privkey1, address1) state1.register_secretmessage(secret_message) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 - lock_amount assert state2.balance(state1) == balance2 + lock_amount assert state1.distributable(state2) == balance1 + 10 - lock_amount assert state2.distributable(state1) == balance2 + lock_amount assert state1.amount_locked == 0 assert state2.amount_locked == 0 assert state1.is_locked(lock_hashlock) is False assert state2.is_locked(lock_hashlock) is False assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT assert state1.nonce is 2 assert state2.nonce is None
def test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_protocol): """ Multiple RevealSecret messages arriving at the same time must be handled properly. Secret handling followed these steps: The Secret message arrives The secret is registered The channel is updated and the correspoding lock is removed * A balance proof for the new channel state is created and sent to the payer The channel is unregistered for the given secrethash The step marked with an asterisk above introduced a context-switch. This allowed a second Reveal Secret message to be handled before the channel was unregistered. And because the channel was already updated an exception was raised for an unknown secret. """ app0, app1 = raiden_network token = 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, ) channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) payment_identifier = 1 secret = sha3(b'test_regression_multiple_revealsecret') secrethash = sha3(secret) expiration = app0.raiden.get_block_number() + 100 lock_amount = 10 lock = Lock( lock_amount, expiration, secrethash, ) nonce = 1 transferred_amount = 0 mediated_transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=nonce, token_network_address=app0.raiden.default_registry.address, token=token, channel_identifier=channelstate_0_1.identifier, transferred_amount=transferred_amount, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=lock.secrethash, lock=lock, target=app1.raiden.address, initiator=app0.raiden.address, ) app0.raiden.sign(mediated_transfer) if transport_protocol is TransportProtocol.UDP: message_data = mediated_transfer.encode() host_port = None app1.raiden.transport.receive(message_data, host_port) elif transport_protocol is TransportProtocol.MATRIX: app1.raiden.transport._receive_message(mediated_transfer) else: raise TypeError('Unknown TransportProtocol') reveal_secret = RevealSecret( random.randint(0, UINT64_MAX), secret, ) app0.raiden.sign(reveal_secret) token_network_identifier = channelstate_0_1.token_network_identifier secret = Secret( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=mediated_transfer.nonce + 1, token_network_address=token_network_identifier, channel_identifier=channelstate_0_1.identifier, transferred_amount=lock_amount, locked_amount=0, locksroot=EMPTY_MERKLE_ROOT, secret=secret, ) app0.raiden.sign(secret) if transport_protocol is TransportProtocol.UDP: messages = [ secret.encode(), reveal_secret.encode(), ] host_port = None receive_method = app1.raiden.transport.receive wait = [ gevent.spawn_later( .1, receive_method, data, host_port, ) for data in messages ] elif transport_protocol is TransportProtocol.MATRIX: messages = [ secret, reveal_secret, ] receive_method = app1.raiden.transport._receive_message wait = [ gevent.spawn_later( .1, receive_method, data, ) for data in messages ] else: raise TypeError('Unknown TransportProtocol') gevent.joinall(wait)
def make_signed_transfer( amount: typing.TokenAmount = EMPTY, initiator: typing.InitiatorAddress = EMPTY, target: typing.TargetAddress = EMPTY, expiration: typing.BlockExpiration = EMPTY, secret: typing.Secret = EMPTY, payment_identifier: typing.PaymentID = EMPTY, message_identifier: typing.MessageID = EMPTY, nonce: typing.Nonce = EMPTY, transferred_amount: typing.TokenAmount = EMPTY, locked_amount: typing.TokenAmount = EMPTY, locksroot: typing.Locksroot = EMPTY, recipient: typing.Address = EMPTY, channel_identifier: typing.ChannelID = EMPTY, token_network_address: typing.TokenNetworkID = EMPTY, token: typing.TargetAddress = EMPTY, pkey: PrivateKey = EMPTY, sender: typing.Address = EMPTY, ) -> LockedTransferSignedState: amount = if_empty(amount, UNIT_TRANSFER_AMOUNT) initiator = if_empty(initiator, make_address()) target = if_empty(target, make_address()) expiration = if_empty(expiration, UNIT_REVEAL_TIMEOUT) secret = if_empty(secret, make_secret()) payment_identifier = if_empty(payment_identifier, 1) message_identifier = if_empty(message_identifier, make_message_identifier()) nonce = if_empty(nonce, 1) transferred_amount = if_empty(transferred_amount, 0) locked_amount = if_empty(locked_amount, amount) locksroot = if_empty(locksroot, EMPTY_MERKLE_ROOT) recipient = if_empty(recipient, UNIT_TRANSFER_TARGET) channel_identifier = if_empty(channel_identifier, UNIT_CHANNEL_ID) token_network_address = if_empty(token_network_address, UNIT_TOKEN_NETWORK_ADDRESS) token = if_empty(token, UNIT_TOKEN_ADDRESS) pkey = if_empty(pkey, UNIT_TRANSFER_PKEY) sender = if_empty(sender, UNIT_TRANSFER_SENDER) assert locked_amount >= amount secrethash = sha3(secret) lock = Lock( amount=amount, expiration=expiration, secrethash=secrethash, ) if locksroot == EMPTY_MERKLE_ROOT: locksroot = sha3(lock.as_bytes) 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 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']
def test_end_state(): asset_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 lock_secret = sha3('test_end_state') lock_amount = 30 lock_expiration = 10 lock_hashlock = sha3(lock_secret) state1 = ChannelEndState(address1, balance1) state2 = ChannelEndState(address2, balance2) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == 0 assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == '' lock = Lock( lock_amount, lock_expiration, lock_hashlock, ) lock_hash = sha3(lock.as_bytes) transferred_amount = 0 locksroot = state2.compute_merkleroot_with(lock) locked_transfer = LockedTransfer( 1, # TODO: fill in identifier nonce=state1.nonce, asset=asset_address, transferred_amount=transferred_amount, recipient=state2.address, locksroot=locksroot, lock=lock, ) transfer_target = make_address() transfer_initiator = make_address() fee = 0 mediated_transfer = locked_transfer.to_mediatedtransfer( transfer_target, transfer_initiator, fee, ) mediated_transfer.sign(privkey1, address1) state2.register_locked_transfer(mediated_transfer) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is True assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash with pytest.raises(ValueError): state1.update_contract_balance(balance1 - 10) state1.update_contract_balance(balance1 + 10) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount + 10 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is True assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash # registering the secret should not change the locked amount state2.register_secret(lock_secret) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount + 10 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash state2.release_lock(state1, lock_secret) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 - lock_amount assert state2.balance(state1) == balance2 + lock_amount assert state1.distributable(state2) == balance1 + 10 - lock_amount assert state2.distributable(state1) == balance2 + lock_amount assert state1.locked() == 0 assert state2.locked() == 0 assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == ''