def test_transfer_from_outdated(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.token_to_channelgraph.values()[0] graph1 = app1.raiden.token_to_channelgraph.values()[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 result = app0.raiden.transfer_async( graph0.token_address, amount, target=app1.raiden.address, ) assert result.wait(timeout=10) assert_synched_channels(channel0, balance0 - amount, [], channel1, balance1 + amount, []) channel1.external_state.close(channel1.received_transfers[-1], ) wait_until_block(app1.raiden.chain, app1.raiden.chain.block_number() + 1) assert channel0.external_state.close_event.wait(timeout=25) assert channel1.external_state.close_event.wait(timeout=25) assert channel0.external_state.closed_block != 0 assert channel1.external_state.closed_block != 0 wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + settle_timeout, ) assert channel0.external_state.settle_event.wait(timeout=25) assert channel1.external_state.settle_event.wait(timeout=25) assert channel0.external_state.settled_block != 0 assert channel1.external_state.settled_block != 0 # and now receive one more transfer from the closed channel direct_transfer_message = DirectTransfer( identifier=1, nonce=1, token=graph0.token_address, channel=channel0.channel_address, transferred_amount=10, recipient=app0.raiden.address, locksroot=UNIT_HASHLOCK, ) sign_and_send(direct_transfer_message, app1.raiden.private_key, app1.raiden.address, app1)
def test_setup(raiden_network, deposit, assets_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking assets0 = app0.raiden.managers_by_asset_address.keys() assets1 = app1.raiden.managers_by_asset_address.keys() assert len(assets0) == 1 assert len(assets1) == 1 assert assets0 == assets1 assert assets0[0] == assets_addresses[0] asset_address = assets0[0] channel0 = channel(app0, app1, asset_address) channel1 = channel(app1, app0, asset_address) assert channel0 and channel1 assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_transfer(raiden_network, assets_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = channel(app0, app1, assets_addresses[0]) channel1 = channel(app1, app0, assets_addresses[0]) contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance # check agreement on addresses address0 = channel0.our_state.address address1 = channel1.our_state.address app0_asset = app0.raiden.managers_by_asset_address.keys()[0] app1_asset = app1.raiden.managers_by_asset_address.keys()[0] app0_partners = app0.raiden.managers_by_asset_address.values()[0].partneraddress_channel.keys() app1_partners = app1.raiden.managers_by_asset_address.values()[0].partneraddress_channel.keys() assert channel0.asset_address == channel1.asset_address assert app0_asset == app1_asset assert app1.raiden.address in app0_partners assert app0.raiden.address in app1_partners netting_address = channel0.external_state.netting_channel.address netting_channel = app0.raiden.chain.netting_channel(netting_address) # check balances of channel and contract are equal details0 = netting_channel.detail(address0) details1 = netting_channel.detail(address1) assert contract_balance0 == details0['our_balance'] assert contract_balance1 == details1['our_balance'] assert_synched_channels( channel0, contract_balance0, [], channel1, contract_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer( amount, 1 # TODO: fill in identifier ) app0.raiden.sign(direct_transfer) channel0.register_transfer(direct_transfer) channel1.register_transfer(direct_transfer) # check the contract is intact assert details0 == netting_channel.detail(address0) assert details1 == netting_channel.detail(address1) assert channel0.contract_balance == contract_balance0 assert channel1.contract_balance == contract_balance1 assert_synched_channels( channel0, contract_balance0 - amount, [], channel1, contract_balance1 + amount, [], )
def test_setup(raiden_network, deposit, tokens_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking tokens0 = app0.raiden.channelgraphs.keys() tokens1 = app1.raiden.channelgraphs.keys() assert len(tokens0) == 1 assert len(tokens1) == 1 assert tokens0 == tokens1 assert tokens0[0] == tokens_addresses[0] token_address = tokens0[0] channel0 = channel(app0, app1, token_address) channel1 = channel(app1, app0, token_address) assert channel0 and channel1 assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_settlement(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] chain0 = app0.raiden.chain channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = 10 secret = 'secret' hashlock = sha3(secret) assert app1.raiden.address in asset_manager0.partneraddress_channel assert asset_manager0.asset_address == asset_manager1.asset_address assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock) app0.raiden.sign(transfermessage) channel0.register_transfer(transfermessage) channel1.register_transfer(transfermessage) assert_synched_channels( channel0, balance0, [transfermessage.lock], channel1, balance1, [] ) # Bob learns the secret, but Alice did not send a signed updated balance to # reflect this Bob wants to settle # get proof, that locked transfermessage was in merkle tree, with locked.root merkle_proof = channel1.our_state.locked.get_proof(transfermessage) root = channel1.our_state.locked.root assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes)) channel0.external_state.netting_channel.close( app0.raiden.address, transfermessage, None, ) unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)] channel0.external_state.netting_channel.unlock( app0.raiden.address, unlocked, ) for _ in range(settle_timeout): chain0.next_block() channel0.external_state.netting_channel.settle()
def test_settlement(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] chain0 = app0.raiden.chain channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = 5 secret = 'secret' hashlock = sha3(secret) assert app1.raiden.address in asset_manager0.partneraddress_channel assert asset_manager0.asset_address == asset_manager1.asset_address assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock) app0.raiden.sign(transfermessage) channel0.register_transfer(transfermessage) channel1.register_transfer(transfermessage) assert_synched_channels( channel0, balance0, [transfermessage.lock], channel1, balance1, [] ) # Bob learns the secret, but Alice did not send a signed updated balance to # reflect this Bob wants to settle # get proof, that locked transfermessage was in merkle tree, with locked.root merkle_proof = channel1.our_state.locked.get_proof(transfermessage) root = channel1.our_state.locked.root assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes)) channel0.external_state.netting_channel.close( app0.raiden.address, transfermessage, None, ) unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)] channel0.external_state.netting_channel.unlock( app0.raiden.address, unlocked, ) for _ in range(settle_timeout): chain0.next_block() channel0.external_state.netting_channel.settle()
def test_secret_revealed(deployed_network, deposit): app0, app1, app2 = deployed_network asset_address = app0.raiden.chain.default_registry.asset_addresses()[0] amount = 10 secret = pending_mediated_transfer(deployed_network, asset_address, amount) mediated_transfer = get_received_transfer( channel(app2, app1, asset_address), 0, ) merkle_proof = channel(app2, app1, asset_address).our_state.locked.get_proof(mediated_transfer) channel(app2, app1, asset_address).netting_contract.unlock( [(merkle_proof, mediated_transfer.lock, secret)], ) gevent.sleep(0.1) # let the task run assert_synched_channels( channel(app1, app2, asset_address), deposit - amount, [], channel(app2, app1, asset_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, asset_address), deposit - amount, [], channel(app1, app2, asset_address), deposit + amount, [], )
def test_secret_revealed(raiden_chain, deposit, settle_timeout, events_poll_timeout): app0, app1, app2 = raiden_chain asset_address = app0.raiden.chain.default_registry.asset_addresses()[0] amount = 10 channel21 = channel(app2, app1, asset_address) netting_channel = channel21.external_state.netting_channel secret = pending_mediated_transfer( raiden_chain, asset_address, amount, 1 # TODO: fill in identifier ) hashlock = sha3(secret) gevent.sleep(.1) # wait for the messages balance_proof = channel21.our_state.balance_proof lock = balance_proof.get_lock_by_hashlock(hashlock) proof = balance_proof.compute_proof_for_lock(secret, lock) # the secret hasn't been revealed yet (through messages) assert len(balance_proof.hashlock_pendinglocks) == 1 proofs = list(balance_proof.get_known_unlocks()) assert len(proofs) == 0 netting_channel.close(app2.raiden.address, balance_proof.transfer, None) # reveal it through the blockchain (this needs to emit the SecretRevealed event) netting_channel.unlock( app2.raiden.address, [proof], ) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) channel21.settle_event.wait(timeout=10) assert_synched_channels( channel(app1, app2, asset_address), deposit - amount, [], channel(app2, app1, asset_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, asset_address), deposit - amount, [], channel(app1, app2, asset_address), deposit + amount, [], )
def test_locked_transfer(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel.values()[0] channel1 = graph1.partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 # reveal_timeout <= expiration < contract.lock_time block_number = app0.raiden.chain.block_number() expiration = block_number + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) mediated_transfer = channel0.create_mediatedtransfer( block_number, transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=1, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(mediated_transfer) channel0.register_transfer(mediated_transfer) channel1.register_transfer(mediated_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [], channel1, balance1, [mediated_transfer.lock], ) channel0.release_lock(secret) channel1.withdraw_lock(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_transfer_from_outdated(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking token_manager0 = app0.raiden.managers_by_token_address.values()[0] token_manager1 = app1.raiden.managers_by_token_address.values()[0] channel0 = token_manager0.partneraddress_channel[app1.raiden.address] channel1 = token_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert token_manager0.token_address == token_manager1.token_address assert app1.raiden.address in token_manager0.partneraddress_channel amount = 10 app0.raiden.api.transfer( token_manager0.token_address, amount, target=app1.raiden.address, ) assert_synched_channels(channel0, balance0 - amount, [], channel1, balance1 + amount, []) app1.raiden.api.close(token_manager0.token_address, app0.raiden.address) wait_until_block(app1.raiden.chain, app1.raiden.chain.block_number() + 1) assert channel0.close_event.wait(timeout=25) assert channel1.close_event.wait(timeout=25) assert channel0.external_state.closed_block != 0 assert channel1.external_state.closed_block != 0 wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + settle_timeout, ) assert channel0.settle_event.wait(timeout=25) assert channel1.settle_event.wait(timeout=25) assert channel0.external_state.settled_block != 0 assert channel1.external_state.settled_block != 0 # and now receive one more transfer from the closed channel direct_transfer = DirectTransfer(identifier=1, nonce=1, token=token_manager0.token_address, transferred_amount=10, recipient=app0.raiden.address, locksroot=HASH) sign_and_send(direct_transfer, app1.raiden.private_key, app1.raiden.address, app1)
def test_token_swap(raiden_network, deposit, settle_timeout): app0, app1 = raiden_network maker_address = app0.raiden.address taker_address = app1.raiden.address maker_token, taker_token = list( app0.raiden.token_to_channelgraph.keys())[:2] maker_amount = 70 taker_amount = 30 identifier = 313 RaidenAPI(app1.raiden).expect_token_swap( identifier, maker_token, maker_amount, maker_address, taker_token, taker_amount, taker_address, ) async_result = RaidenAPI(app0.raiden).token_swap_async( identifier, maker_token, maker_amount, maker_address, taker_token, taker_amount, taker_address, ) assert async_result.wait() # wait for the taker to receive and process the messages gevent.sleep(0.5) assert_synched_channels( channel(app0, app1, maker_token), deposit - maker_amount, [], channel(app1, app0, maker_token), deposit + maker_amount, [], ) assert_synched_channels( channel(app0, app1, taker_token), deposit + taker_amount, [], channel(app1, app0, taker_token), deposit - taker_amount, [], )
def test_transfer_from_outdated(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking tester_state = app0.raiden.chain.tester_state asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert asset_manager0.asset_address == asset_manager1.asset_address assert app1.raiden.address in asset_manager0.partneraddress_channel amount = 10 app0.raiden.api.transfer( asset_manager0.asset_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) app1.raiden.api.close(asset_manager0.asset_address, app0.raiden.address) tester_state.mine(1) gevent.sleep(.5) tester_state.mine(number_of_blocks=settle_timeout + 1) app0.raiden.api.settle(asset_manager0.asset_address, app1.raiden.address) gevent.sleep(.5) assert channel0.external_state.settled_block != 0 assert channel1.external_state.settled_block != 0 # and now receive one more transfer from the closed channel direct_transfer = DirectTransfer( identifier=1, nonce=1, asset=asset_manager0.asset_address, transferred_amount=10, recipient=app0.raiden.address, locksroot=HASH ) sign_and_send( direct_transfer, app1.raiden.private_key, app1.raiden.address, app1 )
def test_secret_revealed(raiden_chain, deposit, settle_timeout, events_poll_timeout): app0, app1, app2 = raiden_chain token_address = app0.raiden.default_registry.token_addresses()[0] amount = 10 channel21 = channel(app2, app1, token_address) netting_channel = channel21.external_state.netting_channel identifier = 1 expiration = app2.raiden.get_block_number() + settle_timeout - 3 secret = pending_mediated_transfer( raiden_chain, token_address, amount, identifier, expiration, ) hashlock = sha3(secret) gevent.sleep(.1) # wait for the messages lock = channel21.our_state.get_lock_by_hashlock(hashlock) proof = channel21.our_state.compute_proof_for_lock(secret, lock) # the secret hasn't been revealed yet (through messages) assert len(channel21.our_state.hashlocks_to_pendinglocks) == 1 proofs = list(channel21.our_state.get_known_unlocks()) assert len(proofs) == 0 netting_channel.close(channel21.our_state.balance_proof) # reveal it through the blockchain (this needs to emit the SecretRevealed event) netting_channel.withdraw( app2.raiden.address, [proof], ) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) channel21.settle_event.wait(timeout=10) assert_synched_channels( channel(app1, app2, token_address), deposit - amount, [], channel(app2, app1, token_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, token_address), deposit - amount, [], channel(app1, app2, token_address), deposit + amount, [], )
def test_locked_transfer(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 # reveal_timeout <= expiration < contract.lock_time expiration = app0.raiden.chain.block_number() + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [], channel1, balance1, [locked_transfer.lock], ) channel0.release_lock(secret) channel1.withdraw_lock(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_locked_transfer(): """ Simple locked transfer test. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 # reveal_timeout <= expiration < contract.lock_time secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [locked_transfer.lock], channel1, balance1, [], ) channel0.claim_locked(secret) channel1.claim_locked(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_receive_directtransfer_outoforder(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel[app1.raiden.address] channel1 = graph1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_channel amount = 10 target = app1.raiden.address result = app0.raiden.transfer_async( graph0.token_address, amount, target, ) assert result.wait(timeout=10) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) # and now send one more direct transfer with the same nonce, simulating # an out-of-order/resent message that arrives late identifier = create_default_identifier( app0.raiden.address, graph0.token_address, app1.raiden.address, ) direct_transfer = DirectTransfer( identifier=identifier, nonce=1, token=graph0.token_address, transferred_amount=10, recipient=app1.raiden.address, locksroot=HASH, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer, app0_key, app0.raiden.address, app1)
def test_receive_directtransfer_outoforder(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 target = app1.raiden.address result = app0.raiden.direct_transfer_async( graph0.token_address, amount, target, identifier=1, ) assert result.wait(timeout=10) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) # and now send one more direct transfer with the same nonce, simulating # an out-of-order/resent message that arrives late identifier = create_default_identifier() direct_transfer_message = DirectTransfer( identifier=identifier, nonce=1, token=graph0.token_address, channel=channel0.channel_address, transferred_amount=10, recipient=app1.raiden.address, locksroot=UNIT_HASHLOCK, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer_message, app0_key, app0.raiden.address, app1)
def test_direct_transfer(raiden_network): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 target = app1.raiden.address result = app0.raiden.direct_transfer_async( graph0.token_address, amount, target, identifier=1, ) assert result.wait(timeout=10) gevent.sleep(5) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) decoded_messages = [decode(m) for m in messages] direct_messages = get_messages_by_type(decoded_messages, DirectTransfer) assert len(direct_messages) == 1 assert direct_messages[0].transferred_amount == amount assert_ack_for( app1, direct_messages[0], decoded_messages, )
def test_token_swap(raiden_network, deposit, settle_timeout): app0, app1 = raiden_network maker_address = app0.raiden.address taker_address = app1.raiden.address maker_token, taker_token = list(app0.raiden.token_to_channelgraph.keys())[:2] maker_amount = 70 taker_amount = 30 identifier = 313 RaidenAPI(app1.raiden).expect_token_swap( identifier, maker_token, maker_amount, maker_address, taker_token, taker_amount, taker_address, ) async_result = RaidenAPI(app0.raiden).token_swap_async( identifier, maker_token, maker_amount, maker_address, taker_token, taker_amount, taker_address, ) assert async_result.wait() # wait for the taker to receive and process the messages gevent.sleep(0.5) assert_synched_channels( channel(app0, app1, maker_token), deposit - maker_amount, [], channel(app1, app0, maker_token), deposit + maker_amount, [], ) assert_synched_channels( channel(app0, app1, taker_token), deposit + taker_amount, [], channel(app1, app0, taker_token), deposit - taker_amount, [], )
def test_direct_transfer(raiden_network): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() graph0 = app0.raiden.token_to_channelgraph.values()[0] graph1 = app1.raiden.token_to_channelgraph.values()[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 target = app1.raiden.address result = app0.raiden.direct_transfer_async( graph0.token_address, amount, target, identifier=1, ) result.wait(timeout=10) gevent.sleep(5) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) decoded_messages = [decode(m) for m in messages] direct_messages = get_messages_by_type(decoded_messages, DirectTransfer) assert len(direct_messages) == 1 assert direct_messages[0].transferred_amount == amount assert_ack_for( app1, direct_messages[0], decoded_messages, )
def test_receive_directtransfer_invalidlocksroot(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.token_to_channelgraph.values()[0] graph1 = app1.raiden.token_to_channelgraph.values()[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 result = app0.raiden.direct_transfer_async( graph0.token_address, amount, target=app1.raiden.address, identifier=1, ) assert result.wait(timeout=10) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) # and now send one more direct transfer with the locksroot not set correctly identifier = create_default_identifier() direct_transfer_message = DirectTransfer( identifier=identifier, nonce=2, token=graph0.token_address, channel=channel0.channel_address, transferred_amount=10, recipient=app1.raiden.address, locksroot=UNIT_HASHLOCK, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer_message, app0_key, app0.raiden.address, app1)
def test_receive_directtransfer_wrongtoken(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel[app1.raiden.address] channel1 = graph1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_channel amount = 10 app0.raiden.api.transfer( graph0.token_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) # and now send one more direct transfer with a mistaken token address identifier = create_default_identifier( app0.raiden.address, graph0.token_address, app1.raiden.address, ) direct_transfer = DirectTransfer( identifier=identifier, nonce=2, token=HASH[0:20], transferred_amount=10, recipient=app1.raiden.address, locksroot=HASH, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer, app0_key, app0.raiden.address, app1)
def test_locked_transfer(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 # reveal_timeout <= expiration < contract.lock_time expiration = app0.raiden.chain.block_number() + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [], channel1, balance1, [locked_transfer.lock], ) channel0.release_lock(secret) channel1.withdraw_lock(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_locked_transfer(): """ Simple locked transfer test. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 # min_locktime <= expiration < contract.lock_time secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [locked_transfer.lock], channel1, balance1, [], ) channel0.claim_locked(secret) channel1.claim_locked(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_setup(raiden_network, deposit, token_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking tokens0 = list(app0.raiden.token_to_channelgraph.keys()) tokens1 = list(app1.raiden.token_to_channelgraph.keys()) assert len(tokens0) == 1 assert len(tokens1) == 1 assert tokens0 == tokens1 assert tokens0[0] == token_addresses[0] token_address = tokens0[0] channel0 = channel(app0, app1, token_address) channel1 = channel(app1, app0, token_address) assert channel0 and channel1 assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_receive_directtransfer_invalidlocksroot(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking token_manager0 = app0.raiden.managers_by_token_address.values()[0] token_manager1 = app1.raiden.managers_by_token_address.values()[0] channel0 = token_manager0.partneraddress_channel[app1.raiden.address] channel1 = token_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert token_manager0.token_address == token_manager1.token_address assert app1.raiden.address in token_manager0.partneraddress_channel amount = 10 app0.raiden.api.transfer( token_manager0.token_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels(channel0, balance0 - amount, [], channel1, balance1 + amount, []) # and now send one more direct transfer with the locksroot not set correctly direct_transfer = DirectTransfer( identifier=app0.raiden.api.create_default_identifier( app1.raiden.address, token_manager0.token_address, ), nonce=2, token=token_manager0.token_address, transferred_amount=10, recipient=app1.raiden.address, locksroot=HASH, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer, app0_key, app0.raiden.address, app1)
def test_receive_directtransfer_outoforder(raiden_network, private_keys): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert asset_manager0.asset_address == asset_manager1.asset_address assert app1.raiden.address in asset_manager0.partneraddress_channel amount = 10 app0.raiden.api.transfer( asset_manager0.asset_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) # and now send one more direct transfer with the same nonce, simulating # an out-of-order/resent message that arrives late direct_transfer = DirectTransfer( identifier=asset_manager0.transfermanager.create_default_identifier(app1.raiden.address), nonce=1, asset=asset_manager0.asset_address, transferred_amount=10, recipient=app1.raiden.address, locksroot=HASH, ) app0_key = PrivateKey(private_keys[0]) sign_and_send(direct_transfer, app0_key, app0.raiden.address, app1)
def test_secret_revealed(deployed_network, deposit): app0, app1, app2 = deployed_network asset_address = app0.raiden.chain.default_registry.asset_addresses()[0] amount = 10 secret = pending_mediated_transfer(deployed_network, asset_address, amount) mediated_transfer = get_received_transfer( channel(app2, app1, asset_address), 0, ) merkle_proof = channel( app2, app1, asset_address).our_state.locked.get_proof(mediated_transfer) channel(app2, app1, asset_address).netting_contract.unlock( [(merkle_proof, mediated_transfer.lock, secret)], ) gevent.sleep(0.1) # let the task run assert_synched_channels( channel(app1, app2, asset_address), deposit - amount, [], channel(app2, app1, asset_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, asset_address), deposit - amount, [], channel(app1, app2, asset_address), deposit + amount, [], )
def test_transfer(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance # check agreement on addresses address0 = channel0.our_state.address address1 = channel1.our_state.address assert channel0.asset_address == channel1.asset_address assert app0.raiden.assetmanagers.keys()[0] == app1.raiden.assetmanagers.keys()[0] assert app0.raiden.assetmanagers.values()[0].channels.keys()[0] == app1.raiden.address assert app1.raiden.assetmanagers.values()[0].channels.keys()[0] == app0.raiden.address # check balances of channel and contract are equal details0 = app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) details1 = app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert initial_balance0 == details0['our_balance'] assert initial_balance1 == details1['our_balance'] assert_synched_channels( channel0, initial_balance0, [], channel1, initial_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer(amount=amount) app0.raiden.sign(direct_transfer) channel0.register_transfer(direct_transfer) channel1.register_transfer(direct_transfer) # check the contract is intact assert details0 == app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) assert details1 == app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert channel0.initial_balance == initial_balance0 assert channel1.initial_balance == initial_balance1 assert_synched_channels( channel0, initial_balance0 - amount, [], channel1, initial_balance1 + amount, [], )
def test_register_invalid_transfer(): """ Regression test for registration of invalid transfer. Bhe bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners asset, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.our_state.balance balance1 = channel1.our_state.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [transfer1.lock], channel1, balance1, [], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( nonce=channel0.our_state.nonce, asset=channel0.asset_address, balance=channel0.partner_state.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.locked.root, secret=secret, ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels( channel0, balance0, [transfer1.lock], channel1, balance1, [] )
def test_interwoven_transfers(num=100): # pylint: disable=too-many-locals """ Can keep doing transaction even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance expiration = app0.raiden.chain.block_number + 15 unclaimed_locks = [] transfers_list = [] transfers_amount = [i for i in range(1, num + 1)] # start at 1 because we can't use amount=0 transfers_secret = [str(i) for i in range(num)] transfers_claimed = [] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(locked_transfer) unclaimed_locks.append(locked_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.claim_locked(secret) channel1.claim_locked(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount
def test_event_new_channel(raiden_chain, deposit, settle_timeout, events_poll_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_address = app0.raiden.default_registry.token_addresses()[0] assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 0 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 0 token0 = app0.raiden.chain.token(token_address) graph0 = app0.raiden.default_registry.manager_by_token(token_address) token1 = app1.raiden.chain.token(token_address) netcontract_address = graph0.new_netting_channel( app0.raiden.address, app1.raiden.address, settle_timeout, ) netting_channel0 = app0.raiden.chain.netting_channel(netcontract_address) netting_channel1 = app1.raiden.chain.netting_channel(netcontract_address) gevent.sleep(events_poll_timeout) # channel is created but not opened and without funds assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 channel0 = app0.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] channel1 = app1.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] assert_synched_channels( channel0, 0, [], channel1, 0, [], ) token0.approve(netcontract_address, deposit) netting_channel0.deposit(deposit) gevent.sleep(events_poll_timeout) # channel is open but single funded assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 channel0 = app0.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] channel1 = app1.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] assert_synched_channels( channel0, deposit, [], channel1, 0, [], ) token1.approve(netcontract_address, deposit) netting_channel1.deposit(deposit) gevent.sleep(events_poll_timeout) # channel is open and funded by both participants assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 channel0 = app0.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] channel1 = app1.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_query_events(raiden_chain, deposit, settle_timeout, events_poll_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_address = app0.raiden.default_registry.token_addresses()[0] assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 0 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 0 token0 = app0.raiden.chain.token(token_address) manager0 = app0.raiden.default_registry.manager_by_token(token_address) events = get_all_registry_events( app0.raiden.chain, app0.raiden.default_registry.address, events=ALL_EVENTS, from_block=0, to_block='latest', ) assert len(events) == 1 assert event_dicts_are_equal( events[0], { '_event_type': 'TokenAdded', 'channel_manager_address': address_encoder(manager0.address), 'token_address': address_encoder(token_address), 'block_number': 'ignore', }) events = get_all_registry_events( app0.raiden.chain, app0.raiden.default_registry.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events netcontract_address = manager0.new_netting_channel( app0.raiden.address, app1.raiden.address, settle_timeout, ) events = get_all_channel_manager_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=0, to_block='latest', ) assert len(events) == 1 assert event_dicts_are_equal( events[0], { '_event_type': 'ChannelNew', 'settle_timeout': settle_timeout, 'netting_channel': address_encoder(netcontract_address), 'participant1': address_encoder(app0.raiden.address), 'participant2': address_encoder(app1.raiden.address), 'block_number': 'ignore', }) events = get_all_channel_manager_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events netting_channel0 = app0.raiden.chain.netting_channel(netcontract_address) gevent.sleep(events_poll_timeout * 2) # channel is created but not opened and without funds assert len(app0.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address]. address_to_channel) == 1 channel0 = app0.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] channel1 = app1.raiden.token_to_channelgraph[ token_address].address_to_channel.values()[0] assert_synched_channels( channel0, 0, [], channel1, 0, [], ) token0.approve(netcontract_address, deposit) netting_channel0.deposit(deposit) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=netcontract_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, netcontract_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)], ) assert len(all_netting_channel_events) == 1 assert len(events) == 1 new_balance_event = { '_event_type': 'ChannelNewBalance', 'token_address': address_encoder(token_address), 'participant': address_encoder(app0.raiden.address), 'balance': deposit, 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1], new_balance_event) assert event_dicts_are_equal(events[0], new_balance_event) channel0.external_state.close(None) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=netcontract_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, netcontract_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)], ) assert len(all_netting_channel_events) == 2 assert len(events) == 1 closed_event = { '_event_type': 'ChannelClosed', 'closing_address': address_encoder(app0.raiden.address), 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1], closed_event) assert event_dicts_are_equal(events[0], closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 1 wait_until_block(app0.raiden.chain, settle_expiration) channel1.external_state.settle() all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=netcontract_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, netcontract_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)], ) assert len(all_netting_channel_events) == 3 assert len(events) == 1 settled_event = { '_event_type': 'ChannelSettled', 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1], settled_event) assert event_dicts_are_equal(events[0], settled_event)
def test_transfer(raiden_network): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() mlogger = MessageLogger() a0_address = pex(app0.raiden.address) a1_address = pex(app1.raiden.address) asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert asset_manager0.asset_address == asset_manager1.asset_address assert app1.raiden.address in asset_manager0.partneraddress_channel amount = 10 app0.raiden.api.transfer( asset_manager0.asset_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) assert len(messages) == 2 # DirectTransfer, Ack directtransfer_message = decode(messages[0]) assert isinstance(directtransfer_message, DirectTransfer) assert directtransfer_message.transferred_amount == amount ack_message = decode(messages[1]) assert isinstance(ack_message, Ack) assert ack_message.echo == sha3(directtransfer_message.encode() + app1.raiden.address) a0_messages = mlogger.get_node_messages(a0_address) assert len(a0_messages) == 2 assert isinstance(a0_messages[0], DirectTransfer) assert isinstance(a0_messages[1], Ack) a0_sent_messages = mlogger.get_node_messages(a0_address, only='sent') assert len(a0_sent_messages) == 1 assert isinstance(a0_sent_messages[0], DirectTransfer) a0_recv_messages = mlogger.get_node_messages(a0_address, only='recv') assert len(a0_recv_messages) == 1 assert isinstance(a0_recv_messages[0], Ack) a1_messages = mlogger.get_node_messages(a1_address) assert len(a1_messages) == 2 assert isinstance(a1_messages[0], Ack) assert isinstance(a1_messages[1], DirectTransfer) a1_sent_messages = mlogger.get_node_messages(a1_address, only='sent') assert len(a1_sent_messages) == 1 assert isinstance(a1_sent_messages[0], Ack) a1_recv_messages = mlogger.get_node_messages(a1_address, only='recv') assert len(a1_recv_messages) == 1 assert isinstance(a1_recv_messages[0], DirectTransfer)
def test_cancel_transfer(raiden_chain, token_addresses, deposit): """ A failed transfer must send a refund back. TODO: - Unlock the token on refund #1091 - Clear the merkletree and update the locked amount #193 - Remove the refund message type #490 """ # Topology: # # 0 -> 1 -> 2 # app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token = token_addresses[0] assert_synched_channels( channel(app0, app1, token), deposit, [], channel(app1, app0, token), deposit, [] ) assert_synched_channels( channel(app1, app2, token), deposit, [], channel(app2, app1, token), deposit, [] ) # make a transfer to test the path app0 -> app1 -> app2 identifier_path = 1 amount_path = 1 transfer(app0, app2, token, amount_path, identifier_path) # drain the channel app1 -> app2 identifier_drain = 2 amount_drain = int(deposit * 0.8) direct_transfer(app1, app2, token, amount_drain, identifier_drain) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channels( channel(app0, app1, token), deposit - amount_path, [], channel(app1, app0, token), deposit + amount_path, [] ) assert_synched_channels( channel(app1, app2, token), deposit - amount_path - amount_drain, [], channel(app2, app1, token), deposit + amount_path + amount_drain, [] ) # app0 -> app1 -> app2 is the only available path but the channel app1 -> # app2 doesnt have resources and needs to send a RefundTransfer down the # path identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token, amount_refund, app2.raiden.address, identifier_refund, ) assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # A lock structure with the correct amount app0_messages = app0.raiden.protocol.transport.get_sent_messages(app0.raiden.address) mediated_message = list( message for message in app0_messages if isinstance(message, MediatedTransfer) and message.target == app2.raiden.address )[-1] assert mediated_message app1_messages = app1.raiden.protocol.transport.get_sent_messages(app1.raiden.address) refund_message = next( message for message in app1_messages if isinstance(message, RefundTransfer) and message.recipient == app0.raiden.address ) assert refund_message assert mediated_message.lock.amount == refund_message.lock.amount assert mediated_message.lock.hashlock == refund_message.lock.hashlock assert mediated_message.lock.expiration > refund_message.lock.expiration # Both channels have the amount locked because of the refund message assert_synched_channels( channel(app0, app1, token), deposit - amount_path, [refund_message.lock], channel(app1, app0, token), deposit + amount_path, [mediated_message.lock], ) assert_synched_channels( channel(app1, app2, token), deposit - amount_path - amount_drain, [], channel(app2, app1, token), deposit + amount_path + amount_drain, [] )
def test_interwoven_transfers(number_of_transfers, raiden_network, settle_timeout): """ Can keep doing transaction even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance unclaimed_locks = [] transfers_list = [] transfers_claimed = [] # start at 1 because we can't use amount=0 transfers_amount = [i for i in range(1, number_of_transfers + 1)] transfers_secret = [str(i) for i in range(number_of_transfers)] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): expiration = app0.raiden.chain.block_number() + settle_timeout - 1 locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(locked_transfer) unclaimed_locks.append(locked_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.release_lock(secret) channel1.withdraw_lock(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount
def test_register_invalid_transfer(raiden_network, settle_timeout): """ Regression test for registration of invalid transfer. The bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners asset, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_asset_address.values()[0].partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number() + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( 1, # TODO: fill in identifier nonce=channel0.our_state.nonce, asset=channel0.asset_address, transferred_amount=channel1.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.balance_proof.merkleroot_for_unclaimed(), ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], )
def test_transfer(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() mlogger = MessageLogger() a0_address = pex(app0.raiden.address) a1_address = pex(app1.raiden.address) asset_manager0 = app0.raiden.assetmanagers.values()[0] asset_manager1 = app1.raiden.assetmanagers.values()[0] channel0 = asset_manager0.channels[app1.raiden.address] channel1 = asset_manager1.channels[app0.raiden.address] balance0 = channel0.our_state.balance balance1 = channel1.our_state.balance assert asset_manager0.asset_address == asset_manager1.asset_address assert app1.raiden.address in asset_manager0.channels amount = 10 app0.raiden.api.transfer( asset_manager0.asset_address, amount, target=app1.raiden.address, ) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) assert len(messages) == 2 # DirectTransfer, Ack directtransfer_message = decode(messages[0]) assert isinstance(directtransfer_message, DirectTransfer) assert directtransfer_message.balance == balance1 + amount ack_message = decode(messages[1]) assert isinstance(ack_message, Ack) assert ack_message.echo == directtransfer_message.hash a0_messages = mlogger.get_node_messages(a0_address) assert len(a0_messages) == 2 assert isinstance(a0_messages[0], DirectTransfer) assert isinstance(a0_messages[1], Ack) a0_sent_messages = mlogger.get_node_messages(a0_address, only='sent') assert len(a0_sent_messages) == 1 assert isinstance(a0_sent_messages[0], DirectTransfer) a0_recv_messages = mlogger.get_node_messages(a0_address, only='recv') assert len(a0_recv_messages) == 1 assert isinstance(a0_recv_messages[0], Ack) a1_messages = mlogger.get_node_messages(a1_address) assert len(a1_messages) == 2 assert isinstance(a1_messages[0], Ack) assert isinstance(a1_messages[1], DirectTransfer) a1_sent_messages = mlogger.get_node_messages(a1_address, only='sent') assert len(a1_sent_messages) == 1 assert isinstance(a1_sent_messages[0], Ack) a1_recv_messages = mlogger.get_node_messages(a1_address, only='recv') assert len(a1_recv_messages) == 1 assert isinstance(a1_recv_messages[0], DirectTransfer)
def test_cancel_transfer(raiden_chain, token_addresses, deposit): """ A failed transfer must send a refund back. TODO: - Unlock the token on refund #1091 - Clear the merkletree and update the locked amount #193 - Remove the refund message type #490 """ # Topology: # # 0 -> 1 -> 2 # app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token = token_addresses[0] assert_synched_channels(channel(app0, app1, token), deposit, [], channel(app1, app0, token), deposit, []) assert_synched_channels(channel(app1, app2, token), deposit, [], channel(app2, app1, token), deposit, []) # make a transfer to test the path app0 -> app1 -> app2 identifier_path = 1 amount_path = 1 transfer(app0, app2, token, amount_path, identifier_path) # drain the channel app1 -> app2 identifier_drain = 2 amount_drain = int(deposit * 0.8) direct_transfer(app1, app2, token, amount_drain, identifier_drain) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channels(channel(app0, app1, token), deposit - amount_path, [], channel(app1, app0, token), deposit + amount_path, []) assert_synched_channels(channel(app1, app2, token), deposit - amount_path - amount_drain, [], channel(app2, app1, token), deposit + amount_path + amount_drain, []) # app0 -> app1 -> app2 is the only available path but the channel app1 -> # app2 doesnt have resources and needs to send a RefundTransfer down the # path identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token, amount_refund, app2.raiden.address, identifier_refund, ) assert async_result.wait( ) is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # A lock structure with the correct amount app0_messages = app0.raiden.protocol.transport.get_sent_messages( app0.raiden.address) mediated_message = list(message for message in app0_messages if isinstance(message, MediatedTransfer) and message.target == app2.raiden.address)[-1] assert mediated_message app1_messages = app1.raiden.protocol.transport.get_sent_messages( app1.raiden.address) refund_message = next(message for message in app1_messages if isinstance(message, RefundTransfer) and message.recipient == app0.raiden.address) assert refund_message assert mediated_message.lock.amount == refund_message.lock.amount assert mediated_message.lock.hashlock == refund_message.lock.hashlock assert mediated_message.lock.expiration > refund_message.lock.expiration # Both channels have the amount locked because of the refund message assert_synched_channels( channel(app0, app1, token), deposit - amount_path, [refund_message.lock], channel(app1, app0, token), deposit + amount_path, [mediated_message.lock], ) assert_synched_channels(channel(app1, app2, token), deposit - amount_path - amount_drain, [], channel(app2, app1, token), deposit + amount_path + amount_drain, [])
def test_transfer(raiden_network, token_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = channel(app0, app1, token_addresses[0]) channel1 = channel(app1, app0, token_addresses[0]) contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance app0_token = app0.raiden.token_to_channelgraph.keys()[0] app1_token = app1.raiden.token_to_channelgraph.keys()[0] graph0 = app0.raiden.token_to_channelgraph.values()[0] graph1 = app1.raiden.token_to_channelgraph.values()[0] app0_partners = graph0.partneraddress_to_channel.keys() app1_partners = graph1.partneraddress_to_channel.keys() assert channel0.token_address == channel1.token_address assert app0_token == app1_token assert app1.raiden.address in app0_partners assert app0.raiden.address in app1_partners netting_address = channel0.external_state.netting_channel.address netting_channel = app0.raiden.chain.netting_channel(netting_address) # check balances of channel and contract are equal details0 = netting_channel.detail() details1 = netting_channel.detail() assert contract_balance0 == details0['our_balance'] assert contract_balance1 == details1['our_balance'] assert_synched_channels( channel0, contract_balance0, [], channel1, contract_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer( amount, identifier=1, ) app0.raiden.sign(direct_transfer) channel0.register_transfer( app0.raiden.get_block_number(), direct_transfer, ) channel1.register_transfer( app1.raiden.get_block_number(), direct_transfer, ) # check the contract is intact assert details0 == netting_channel.detail() assert details1 == netting_channel.detail() assert channel0.contract_balance == contract_balance0 assert channel1.contract_balance == contract_balance1 assert_synched_channels( channel0, contract_balance0 - amount, [], channel1, contract_balance1 + amount, [], )
def test_cancel_transfer(raiden_chain, asset, deposit): app0, app1, app2, app3 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() mlogger = MessageLogger() assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) assert_synched_channels( channel(app1, app2, asset), deposit, [], channel(app2, app1, asset), deposit, [] ) assert_synched_channels( channel(app2, app3, asset), deposit, [], channel(app3, app2, asset), deposit, [] ) assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) # drain the channel app1 -> app2 amount12 = 50 direct_transfer(app1, app2, asset, amount12) # drain the channel app2 -> app3 amount23 = 80 direct_transfer(app2, app3, asset, amount23) assert_synched_channels( channel(app1, app2, asset), deposit - amount12, [], channel(app2, app1, asset), deposit + amount12, [] ) assert_synched_channels( channel(app2, app3, asset), deposit - amount23, [], channel(app3, app2, asset), deposit + amount23, [] ) # app1 -> app3 is the only available path but app2 -> app3 doesnt have # resources and needs to send a RefundTransfer down the path transfer(app0, app3, asset, 50) assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) assert_synched_channels( channel(app1, app2, asset), deposit - amount12, [], channel(app2, app1, asset), deposit + amount12, [] ) assert_synched_channels( channel(app2, app3, asset), deposit - amount23, [], channel(app3, app2, asset), deposit + amount23, [] ) assert len(messages) == 12 # DT + DT + SMT + MT + RT + RT + ACKs app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent') assert isinstance(app1_messages[-1], RefundTransfer) app2_messages = mlogger.get_node_messages(pex(app2.raiden.address), only='sent') assert isinstance(app2_messages[-1], RefundTransfer)
def test_settlement(raiden_network, settle_timeout, reveal_timeout): alice_app, bob_app = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() alice_graph = list(alice_app.raiden.token_to_channelgraph.values())[0] bob_graph = list(bob_app.raiden.token_to_channelgraph.values())[0] assert alice_graph.token_address == bob_graph.token_address alice_bob_channel = alice_graph.partneraddress_to_channel[bob_app.raiden.address] bob_alice_channel = bob_graph.partneraddress_to_channel[alice_app.raiden.address] alice_deposit = alice_bob_channel.balance bob_deposit = bob_alice_channel.balance token = alice_app.raiden.chain.token(alice_bob_channel.token_address) alice_balance = token.balance_of(alice_app.raiden.address) bob_balance = token.balance_of(bob_app.raiden.address) alice_chain = alice_app.raiden.chain alice_to_bob_amount = 10 expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1 secret = b'secretsecretsecretsecretsecretse' hashlock = sha3(secret) assert bob_app.raiden.address in alice_graph.partneraddress_to_channel nettingaddress0 = alice_bob_channel.external_state.netting_channel.address nettingaddress1 = bob_alice_channel.external_state.netting_channel.address assert nettingaddress0 == nettingaddress1 identifier = 1 fee = 0 transfermessage = alice_bob_channel.create_mediatedtransfer( alice_app.raiden.address, bob_app.raiden.address, fee, alice_to_bob_amount, identifier, expiration, hashlock, ) alice_app.raiden.sign(transfermessage) alice_bob_channel.register_transfer( alice_app.raiden.get_block_number(), transfermessage, ) bob_alice_channel.register_transfer( bob_app.raiden.get_block_number(), transfermessage, ) assert_synched_channels( alice_bob_channel, alice_deposit, [], bob_alice_channel, bob_deposit, [transfermessage.lock], ) # At this point we are assuming the following: # # A -> B MediatedTransfer # B -> A SecretRequest # A -> B RevealSecret # - protocol didn't continue # # B knowns the secret but doesn't have an updated balance proof, B needs to # call settle. # get proof, that locked transfermessage was in merkle tree, with locked.root lock = bob_alice_channel.partner_state.get_lock_by_hashlock(hashlock) assert sha3(secret) == hashlock unlock_proof = bob_alice_channel.partner_state.compute_proof_for_lock(secret, lock) root = merkleroot(bob_alice_channel.partner_state.merkletree) assert validate_proof( unlock_proof.merkle_proof, root, sha3(transfermessage.lock.as_bytes), ) assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes assert unlock_proof.secret == secret # a ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle balance_proof = transfermessage.to_balanceproof() bob_alice_channel.external_state.close(balance_proof) wait_until_block(alice_chain, alice_chain.block_number() + 1) assert alice_bob_channel.external_state.close_event.wait(timeout=15) assert bob_alice_channel.external_state.close_event.wait(timeout=15) assert alice_bob_channel.external_state.closed_block != 0 assert bob_alice_channel.external_state.closed_block != 0 assert alice_bob_channel.external_state.settled_block == 0 assert bob_alice_channel.external_state.settled_block == 0 # unlock will not be called by Channel.channel_closed because we did not # register the secret assert lock.expiration > alice_app.raiden.chain.block_number() assert lock.hashlock == sha3(secret) bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof]) settle_expiration = alice_chain.block_number() + settle_timeout + 2 wait_until_block(alice_chain, settle_expiration) assert alice_bob_channel.external_state.settle_event.wait(timeout=15) assert bob_alice_channel.external_state.settle_event.wait(timeout=15) # settle must be called by the apps triggered by the ChannelClose event, # and the channels must update it's state based on the ChannelSettled event assert alice_bob_channel.external_state.settled_block != 0 assert bob_alice_channel.external_state.settled_block != 0 address0 = alice_app.raiden.address address1 = bob_app.raiden.address alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount assert token.balance_of(address0) == alice_netted_balance assert token.balance_of(address1) == bob_netted_balance # Now let's query the WAL to see if the state changes were logged as expected state_changes = [ change[1] for change in get_all_state_changes(alice_app.raiden.transaction_log) if not isinstance(change[1], Block) ] assert must_contain_entry(state_changes, ContractReceiveClosed, { 'channel_address': nettingaddress0, 'closing_address': bob_app.raiden.address, 'block_number': alice_bob_channel.external_state.closed_block, }) assert must_contain_entry(state_changes, ReceiveSecretReveal, { 'secret': secret, 'sender': bob_app.raiden.address, }) assert must_contain_entry(state_changes, ContractReceiveWithdraw, { 'channel_address': nettingaddress0, 'secret': secret, 'receiver': bob_app.raiden.address, }) assert must_contain_entry(state_changes, ContractReceiveSettled, { 'channel_address': nettingaddress0, 'block_number': bob_alice_channel.external_state.settled_block, })
def test_interwoven_transfers(number_of_transfers, raiden_network, settle_timeout): """ Can keep doing transaction even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance unclaimed_locks = [] transfers_list = [] transfers_claimed = [] # start at 1 because we can't use amount=0 transfers_amount = [i for i in range(1, number_of_transfers + 1)] transfers_secret = [str(i) for i in range(number_of_transfers)] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): expiration = app0.raiden.chain.block_number() + settle_timeout - 1 locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(locked_transfer) unclaimed_locks.append(locked_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.release_lock(secret) channel1.withdraw_lock(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount
def test_settlement(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() asset_manager0 = app0.raiden.assetmanagers.values()[0] asset_manager1 = app1.raiden.assetmanagers.values()[0] chain0 = app0.raiden.chain asset_address = asset_manager0.asset_address channel0 = asset_manager0.channels[app1.raiden.address] channel1 = asset_manager1.channels[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = 10 secret = 'secret' hashlock = sha3(secret) assert app1.raiden.address in asset_manager0.channels assert asset_manager0.asset_address == asset_manager1.asset_address assert channel0.nettingcontract_address == channel1.nettingcontract_address transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock) app0.raiden.sign(transfermessage) channel0.register_transfer(transfermessage) channel1.register_transfer(transfermessage) assert_synched_channels( channel0, balance0, [transfermessage.lock], channel1, balance1, [] ) # Bob learns the secret, but Alice did not send a signed updated balance to # reflect this Bob wants to settle nettingcontract_address = channel0.nettingcontract_address last_sent_transfers = [transfermessage] # get proof, that locked transfermessage was in merkle tree, with locked.root merkle_proof = channel1.our_state.locked.get_proof(transfermessage) root = channel1.our_state.locked.root assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes)) unlocked = [(merkle_proof, transfermessage.lock, secret)] chain0.close( asset_address, nettingcontract_address, app0.raiden.address, last_sent_transfers, unlocked, ) for _ in range(NettingChannelContract.locked_time): chain0.next_block() chain0.settle(asset_address, nettingcontract_address)
def test_register_invalid_transfer(raiden_network, settle_timeout): """ Regression test for registration of invalid transfer. The bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners' token, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] channel1 = app1.raiden.managers_by_token_address.values( )[0].partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number() + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( 1, # TODO: fill in identifier nonce=channel0.our_state.nonce, token=channel0.token_address, transferred_amount=channel1.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.balance_proof. merkleroot_for_unclaimed(), ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], )
def test_event_new_channel(raiden_chain, deposit, settle_timeout, events_poll_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_address = app0.raiden.default_registry.token_addresses()[0] assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 0 assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 0 token0 = app0.raiden.chain.token(token_address) graph0 = app0.raiden.default_registry.manager_by_token(token_address) token1 = app1.raiden.chain.token(token_address) netcontract_address = graph0.new_netting_channel( app1.raiden.address, settle_timeout, ) netting_channel0 = app0.raiden.chain.netting_channel(netcontract_address) netting_channel1 = app1.raiden.chain.netting_channel(netcontract_address) gevent.sleep(events_poll_timeout) # channel is created but not opened and without funds assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 channel0 = list(app0.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 channel1 = list(app1.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 assert_synched_channels( channel0, 0, [], channel1, 0, [], ) token0.approve(netcontract_address, deposit) netting_channel0.deposit(deposit) gevent.sleep(events_poll_timeout) # channel is open but single funded assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 channel0 = list(app0.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 channel1 = list(app1.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 assert_synched_channels( channel0, deposit, [], channel1, 0, [], ) token1.approve(netcontract_address, deposit) netting_channel1.deposit(deposit) gevent.sleep(events_poll_timeout) # channel is open and funded by both participants assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 1 channel0 = list(app0.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 channel1 = list(app1.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0] # noqa: E501 assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_cancel_transfer(): deposit = 100 asset = sha3('test_cancel_transfer')[:20] # pylint: disable=unbalanced-tuple-unpacking app0, app1, app2 = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset) messages = setup_messages_cb() mlogger = MessageLogger() assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) assert_synched_channels( channel(app1, app2, asset), deposit, [], channel(app2, app1, asset), deposit, [] ) # drain the channel app1 -> app2 amount = 80 direct_transfer(app1, app2, asset, amount) assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) assert_synched_channels( channel(app1, app2, asset), deposit - amount, [], channel(app2, app1, asset), deposit + amount, [] ) # app1 -> app2 is the only available path and doens't have resource, app1 # needs to send CancelTransfer to app0 transfer(app0, app2, asset, 50) assert_synched_channels( channel(app0, app1, asset), deposit, [], channel(app1, app0, asset), deposit, [] ) assert_synched_channels( channel(app1, app2, asset), deposit - amount, [], channel(app2, app1, asset), deposit + amount, [] ) assert len(messages) == 6 # DirectTransfer + MediatedTransfer + CancelTransfer + a Ack for each app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent') assert isinstance(app1_messages[-1], CancelTransfer)
def test_transfer_from_outdated(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] channel0 = graph0.partneraddress_to_channel[app1.raiden.address] channel1 = graph1.partneraddress_to_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_to_channel amount = 10 result = app0.raiden.direct_transfer_async( graph0.token_address, amount, target=app1.raiden.address, identifier=1, ) assert result.wait(timeout=10) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) channel1.external_state.close(channel1.our_state.balance_proof) wait_until_block( app1.raiden.chain, app1.raiden.chain.block_number() + 1 ) assert channel0.external_state.close_event.wait(timeout=25) assert channel1.external_state.close_event.wait(timeout=25) assert channel0.external_state.closed_block != 0 assert channel1.external_state.closed_block != 0 wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + settle_timeout, ) assert channel0.external_state.settle_event.wait(timeout=25) assert channel1.external_state.settle_event.wait(timeout=25) assert channel0.external_state.settled_block != 0 assert channel1.external_state.settled_block != 0 # and now receive one more transfer from the closed channel direct_transfer_message = DirectTransfer( identifier=1, nonce=1, token=graph0.token_address, channel=channel0.channel_address, transferred_amount=10, recipient=app0.raiden.address, locksroot=UNIT_HASHLOCK, ) sign_and_send( direct_transfer_message, app1.raiden.private_key, app1.raiden.address, app1, )
def test_settlement(raiden_network, settle_timeout, reveal_timeout): alice_app, bob_app = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() alice_graph = alice_app.raiden.channelgraphs.values()[0] bob_graph = bob_app.raiden.channelgraphs.values()[0] assert alice_graph.token_address == bob_graph.token_address alice_bob_channel = alice_graph.partneraddress_channel[ bob_app.raiden.address] bob_alice_channel = bob_graph.partneraddress_channel[ alice_app.raiden.address] alice_deposit = alice_bob_channel.balance bob_deposit = bob_alice_channel.balance token = alice_app.raiden.chain.token(alice_bob_channel.token_address) alice_balance = token.balance_of(alice_app.raiden.address) bob_balance = token.balance_of(bob_app.raiden.address) alice_chain = alice_app.raiden.chain alice_to_bob_amount = 10 expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1 secret = 'secretsecretsecretsecretsecretse' hashlock = sha3(secret) assert bob_app.raiden.address in alice_graph.partneraddress_channel nettingaddress0 = alice_bob_channel.external_state.netting_channel.address nettingaddress1 = bob_alice_channel.external_state.netting_channel.address assert nettingaddress0 == nettingaddress1 identifier = 1 fee = 0 transfermessage = alice_bob_channel.create_mediatedtransfer( alice_app.raiden.get_block_number(), alice_app.raiden.address, bob_app.raiden.address, fee, alice_to_bob_amount, identifier, expiration, hashlock, ) alice_app.raiden.sign(transfermessage) alice_bob_channel.register_transfer( alice_app.raiden.get_block_number(), transfermessage, ) bob_alice_channel.register_transfer( bob_app.raiden.get_block_number(), transfermessage, ) assert_synched_channels( alice_bob_channel, alice_deposit, [], bob_alice_channel, bob_deposit, [transfermessage.lock], ) # At this point we are assuming the following: # # A -> B MediatedTransfer # B -> A SecretRequest # A -> B RevealSecret # - protocol didn't continue # # B knowns the secret but doesn't have an updated balance proof, B needs to # call settle. # get proof, that locked transfermessage was in merkle tree, with locked.root lock = bob_alice_channel.our_state.balance_proof.get_lock_by_hashlock( hashlock) assert sha3(secret) == hashlock unlock_proof = bob_alice_channel.our_state.balance_proof.compute_proof_for_lock( secret, lock) root = bob_alice_channel.our_state.balance_proof.merkleroot_for_unclaimed() assert check_proof( unlock_proof.merkle_proof, root, sha3(transfermessage.lock.as_bytes), ) assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes assert unlock_proof.secret == secret # a ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle bob_alice_channel.external_state.netting_channel.close(transfermessage) wait_until_block(alice_chain, alice_chain.block_number() + 1) assert alice_bob_channel.external_state.close_event.wait(timeout=15) assert bob_alice_channel.external_state.close_event.wait(timeout=15) assert alice_bob_channel.external_state.closed_block != 0 assert bob_alice_channel.external_state.closed_block != 0 assert alice_bob_channel.external_state.settled_block == 0 assert bob_alice_channel.external_state.settled_block == 0 # unlock will not be called by Channel.channel_closed because we did not # register the secret assert lock.expiration > alice_app.raiden.chain.block_number() assert lock.hashlock == sha3(secret) bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof]) settle_expiration = alice_chain.block_number() + settle_timeout + 2 wait_until_block(alice_chain, settle_expiration) assert alice_bob_channel.external_state.settle_event.wait(timeout=15) assert bob_alice_channel.external_state.settle_event.wait(timeout=15) # settle must be called by the apps triggered by the ChannelClose event, # and the channels must update it's state based on the ChannelSettled event assert alice_bob_channel.external_state.settled_block != 0 assert bob_alice_channel.external_state.settled_block != 0 address0 = alice_app.raiden.address address1 = bob_app.raiden.address alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount assert token.balance_of(address0) == alice_netted_balance assert token.balance_of(address1) == bob_netted_balance # Now let's query the WAL to see if the state changes were logged as expected state_changes = [ change[1] for change in get_all_state_changes(alice_app.raiden.transaction_log) if not isinstance(change[1], Block) ] state_change1 = state_changes[0] state_change2 = state_changes[1] state_change3 = state_changes[2] state_change4 = state_changes[3] assert isinstance(state_change1, ContractReceiveClosed) assert state_change1.channel_address == nettingaddress0 assert state_change1.closing_address == bob_app.raiden.address assert state_change1.block_number == alice_bob_channel.external_state.closed_block # Can't be sure of the order in which we encounter the SecretReveal and the withdraw assert_secretreveal_or_withdraw(state_change2, secret, nettingaddress0, bob_app.raiden.address) assert_secretreveal_or_withdraw(state_change3, secret, nettingaddress0, bob_app.raiden.address) assert isinstance(state_change4, ContractReceiveSettled) assert state_change4.channel_address == nettingaddress0 assert state_change4.block_number == bob_alice_channel.external_state.settled_block
def test_event_new_channel(deployed_network, deposit, settle_timeout): app0, app1 = deployed_network # pylint: disable=unbalanced-tuple-unpacking asset_address = app0.raiden.chain.asset_addresses[0] assert len(app0.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 0 assert len(app1.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 0 netcontract_address = app0.raiden.chain.new_netting_contract( asset_address, app0.raiden.address, app1.raiden.address, settle_timeout, ) gevent.sleep(0.1) # let the task run # channel is created but not opened and without funds assert len(app0.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 assert len(app1.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 channel0 = app0.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] channel1 = app1.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] assert_synched_channels( channel0, 0, [], channel1, 0, [], ) app0.raiden.chain.asset_approve( asset_address, netcontract_address, deposit, ) app0.raiden.chain.deposit( asset_address, netcontract_address, app0.raiden.address, deposit, ) gevent.sleep(0.1) # let the task run # channel is open but single funded assert len(app0.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 assert len(app1.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 channel0 = app0.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] channel1 = app1.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] assert_synched_channels( channel0, deposit, [], channel1, 0, [], ) app1.raiden.chain.asset_approve( asset_address, netcontract_address, deposit, ) app1.raiden.chain.deposit( asset_address, netcontract_address, app1.raiden.address, deposit, ) # channel is open and funded by both participants assert len(app0.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 assert len(app1.raiden.managers_by_asset_address[asset_address].channels_by_partner) == 1 channel0 = app0.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] channel1 = app1.raiden.managers_by_asset_address[asset_address].channels_by_partner.values()[0] assert_synched_channels( channel0, deposit, [], channel1, deposit, [], )
def test_cancel_transfer(raiden_chain, token, deposit): app0, app1, app2, app3 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() mlogger = MessageLogger() assert_synched_channels( channel(app0, app1, token), deposit, [], channel(app1, app0, token), deposit, [] ) assert_synched_channels( channel(app1, app2, token), deposit, [], channel(app2, app1, token), deposit, [] ) assert_synched_channels( channel(app2, app3, token), deposit, [], channel(app3, app2, token), deposit, [] ) assert_synched_channels( channel(app0, app1, token), deposit, [], channel(app1, app0, token), deposit, [] ) # drain the channel app1 -> app2 amount12 = 50 direct_transfer(app1, app2, token, amount12, identifier=1) # drain the channel app2 -> app3 amount23 = 80 direct_transfer(app2, app3, token, amount23, identifier=2) assert_synched_channels( channel(app1, app2, token), deposit - amount12, [], channel(app2, app1, token), deposit + amount12, [] ) assert_synched_channels( channel(app2, app3, token), deposit - amount23, [], channel(app3, app2, token), deposit + amount23, [] ) # app1 -> app3 is the only available path but app2 -> app3 doesnt have # resources and needs to send a RefundTransfer down the path transfer(app0, app3, token, amount=50, identifier=1) assert_synched_channels( channel(app0, app1, token), deposit, [], channel(app1, app0, token), deposit, [] ) assert_synched_channels( channel(app1, app2, token), deposit - amount12, [], channel(app2, app1, token), deposit + amount12, [] ) assert_synched_channels( channel(app2, app3, token), deposit - amount23, [], channel(app3, app2, token), deposit + amount23, [] ) assert len(unique(messages)) == 12 # DT + DT + SMT + MT + RT + RT + ACKs app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent') assert isinstance(app1_messages[-1], RefundTransfer) app2_messages = mlogger.get_node_messages(pex(app2.raiden.address), only='sent') assert isinstance(app2_messages[-1], RefundTransfer)
def test_transfer(raiden_network, token_addresses): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking channel0 = channel(app0, app1, token_addresses[0]) channel1 = channel(app1, app0, token_addresses[0]) contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance app0_token = list(app0.raiden.token_to_channelgraph.keys())[0] app1_token = list(app1.raiden.token_to_channelgraph.keys())[0] graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] app0_partners = list(graph0.partneraddress_to_channel.keys()) app1_partners = list(graph1.partneraddress_to_channel.keys()) assert channel0.token_address == channel1.token_address assert app0_token == app1_token assert app1.raiden.address in app0_partners assert app0.raiden.address in app1_partners netting_address = channel0.external_state.netting_channel.address netting_channel = app0.raiden.chain.netting_channel(netting_address) # check balances of channel and contract are equal details0 = netting_channel.detail() details1 = netting_channel.detail() assert contract_balance0 == details0['our_balance'] assert contract_balance1 == details1['our_balance'] assert_synched_channels( channel0, contract_balance0, [], channel1, contract_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer( amount, identifier=1, ) app0.raiden.sign(direct_transfer) channel0.register_transfer( app0.raiden.get_block_number(), direct_transfer, ) channel1.register_transfer( app1.raiden.get_block_number(), direct_transfer, ) # check the contract is intact assert details0 == netting_channel.detail() assert details1 == netting_channel.detail() assert channel0.contract_balance == contract_balance0 assert channel1.contract_balance == contract_balance1 assert_synched_channels( channel0, contract_balance0 - amount, [], channel1, contract_balance1 + amount, [], )
def test_transfer(raiden_network): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking messages = setup_messages_cb() mlogger = MessageLogger() a0_address = pex(app0.raiden.address) a1_address = pex(app1.raiden.address) graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel[app1.raiden.address] channel1 = graph1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance assert graph0.token_address == graph1.token_address assert app1.raiden.address in graph0.partneraddress_channel amount = 10 target = app1.raiden.address result = app0.raiden.transfer_async( graph0.token_address, amount, target, ) result.wait(timeout=10) gevent.sleep(1) assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [] ) assert len(messages) == 2 # DirectTransfer, Ack directtransfer_message = decode(messages[0]) assert isinstance(directtransfer_message, DirectTransfer) assert directtransfer_message.transferred_amount == amount ack_message = decode(messages[1]) assert isinstance(ack_message, Ack) assert ack_message.echo == sha3(directtransfer_message.encode() + app1.raiden.address) a0_messages = mlogger.get_node_messages(a0_address) assert len(a0_messages) == 2 assert isinstance(a0_messages[0], DirectTransfer) assert isinstance(a0_messages[1], Ack) a0_sent_messages = mlogger.get_node_messages(a0_address, only='sent') assert len(a0_sent_messages) == 1 assert isinstance(a0_sent_messages[0], DirectTransfer) a0_recv_messages = mlogger.get_node_messages(a0_address, only='recv') assert len(a0_recv_messages) == 1 assert isinstance(a0_recv_messages[0], Ack) a1_messages = mlogger.get_node_messages(a1_address) assert len(a1_messages) == 2 assert isinstance(a1_messages[0], Ack) assert isinstance(a1_messages[1], DirectTransfer) a1_sent_messages = mlogger.get_node_messages(a1_address, only='sent') assert len(a1_sent_messages) == 1 assert isinstance(a1_sent_messages[0], Ack) a1_recv_messages = mlogger.get_node_messages(a1_address, only='recv') assert len(a1_recv_messages) == 1 assert isinstance(a1_recv_messages[0], DirectTransfer)
def test_interwoven_transfers(number_of_transfers, raiden_network, settle_timeout): """ Can keep doing transactions even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] channel0 = list(graph0.partneraddress_to_channel.values())[0] channel1 = list(graph1.partneraddress_to_channel.values())[0] contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance unclaimed_locks = [] transfers_list = [] transfers_claimed = [] # start at 1 because we can't use amount=0 transfers_amount = [i for i in range(1, number_of_transfers + 1)] transfers_secret = [ format(i, '>032') for i in range(number_of_transfers) ] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): block_number = app0.raiden.chain.block_number() expiration = block_number + settle_timeout - 1 identifier = i mediated_transfer = channel0.create_mediatedtransfer( transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=identifier, expiration=expiration, hashlock=sha3(secret.encode()), ) # synchronized registration app0.raiden.sign(mediated_transfer) channel0.register_transfer( block_number, mediated_transfer, ) channel1.register_transfer( block_number, mediated_transfer, ) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(mediated_transfer) unclaimed_locks.append(mediated_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized claiming secret_message = channel0.create_secret( identifier, secret.encode(), ) app0.raiden.sign(secret_message) channel0.register_transfer(block_number, secret_message) channel1.register_transfer(block_number, secret_message) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount
def test_settlement(raiden_network, settle_timeout, reveal_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] chain0 = app0.raiden.chain channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number() + reveal_timeout + 1 secret = 'secret' hashlock = sha3(secret) assert app1.raiden.address in asset_manager0.partneraddress_channel assert asset_manager0.asset_address == asset_manager1.asset_address nettingaddress0 = channel0.external_state.netting_channel.address nettingaddress1 = channel1.external_state.netting_channel.address assert nettingaddress0 == nettingaddress1 identifier = 1 fee = 0 transfermessage = channel0.create_mediatedtransfer( app0.raiden.address, app1.raiden.address, fee, amount, identifier, expiration, hashlock, ) app0.raiden.sign(transfermessage) channel0.register_transfer(transfermessage) channel1.register_transfer(transfermessage) assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfermessage.lock], ) # At this point we are assuming the following: # # A -> B MediatedTransfer # B -> A SecretRequest # A -> B RevealSecret # - protocol didn't continue # # B knowns the secret but doesn't have an updated balance proof, B needs to # call settle. # get proof, that locked transfermessage was in merkle tree, with locked.root lock = channel1.our_state.balance_proof.get_lock_by_hashlock(hashlock) unlock_proof = channel1.our_state.balance_proof.compute_proof_for_lock(secret, lock) root = channel1.our_state.balance_proof.merkleroot_for_unclaimed() assert check_proof( unlock_proof.merkle_proof, root, sha3(transfermessage.lock.as_bytes), ) assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes assert unlock_proof.secret == secret # a ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle channel0.external_state.netting_channel.close( app0.raiden.address, transfermessage, None, ) # unlock will not be called by Channel.channel_closed because we did not # register the secret channel0.external_state.netting_channel.unlock( app0.raiden.address, [unlock_proof], ) settle_expiration = chain0.block_number() + settle_timeout wait_until_block(chain0, settle_expiration) # settle must be called by the apps triggered by the ChannelClose event, # and the channels must update it's state based on the ChannelSettled event assert channel0.external_state.settled_block != 0 assert channel1.external_state.settled_block != 0
def test_locked_transfer(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = list(app0.raiden.token_to_channelgraph.values())[0] graph1 = list(app1.raiden.token_to_channelgraph.values())[0] channel0 = list(graph0.partneraddress_to_channel.values())[0] channel1 = list(graph1.partneraddress_to_channel.values())[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 # reveal_timeout <= expiration < contract.lock_time block_number = app0.raiden.chain.block_number() expiration = block_number + settle_timeout - 1 secret = b'secretsecretsecretsecretsecretse' hashlock = sha3(secret) identifier = 1 mediated_transfer = channel0.create_mediatedtransfer( transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=identifier, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(mediated_transfer) channel0.register_transfer( app0.raiden.chain.block_number(), mediated_transfer, ) channel1.register_transfer( app1.raiden.chain.block_number(), mediated_transfer, ) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [], channel1, balance1, [mediated_transfer.lock], ) secret_message = channel0.create_secret(identifier, secret) app0.raiden.sign(secret_message) channel0.register_transfer( app0.raiden.chain.block_number(), secret_message, ) channel1.register_transfer( app1.raiden.get_block_number(), secret_message, ) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )