def test_raiden_service_callback_new_block(raiden_network): """ Regression test for: https://github.com/raiden-network/raiden/issues/2894 """ app0 = raiden_network[0] app0.raiden.alarm.stop() target_block_num = app0.raiden.chain.block_number( ) + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1 wait_until_block( app0.raiden.chain, target_block_num, ) latest_block = app0.raiden.chain.get_block(block_identifier='latest') app0.raiden._callback_new_block(latest_block=latest_block) target_block_num = latest_block['number'] app0_state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) assert must_contain_entry(app0_state_changes, Block, { 'block_number': target_block_num - DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, }) assert not must_contain_entry(app0_state_changes, Block, { 'block_number': target_block_num, })
def test_channel_with_self(raiden_network, settle_timeout, token_addresses): app0, = raiden_network # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] current_chanels = views.list_channelstate_for_tokennetwork( views.state_from_app(app0), registry_address, token_address, ) assert not current_chanels graph0 = app0.raiden.default_registry.manager_by_token(token_address) with pytest.raises(SamePeerAddress) as excinfo: graph0.new_netting_channel( app0.raiden.address, settle_timeout, ) assert 'The other peer must not have the same address as the client.' in str(excinfo.value) transaction_hash = graph0.proxy.transact('newChannel', app0.raiden.address, settle_timeout) # wait to make sure we get the receipt wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + 5) assert check_transaction_threw(app0.raiden.chain.client, transaction_hash)
def test_raiden_service_callback_new_block(raiden_network): """ Regression test for: https://github.com/raiden-network/raiden/issues/2894 """ app0 = raiden_network[0] app0.raiden.alarm.stop() target_block_num = app0.raiden.chain.block_number() + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1 wait_until_block( app0.raiden.chain, target_block_num, ) latest_block = app0.raiden.chain.get_block(block_identifier='latest') app0.raiden._callback_new_block(latest_block=latest_block) target_block_num = latest_block['number'] app0_state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) assert must_contain_entry(app0_state_changes, Block, { 'block_number': target_block_num - DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, }) assert not must_contain_entry(app0_state_changes, Block, { 'block_number': target_block_num, })
def test_received_directtransfer_closedchannel(raiden_network, token_addresses, deposit): app0, app1 = raiden_network token_address = token_addresses[0] registry_address = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one direct transfer for the closed channel message_identifier = random.randint(0, UINT64_MAX) direct_transfer_message = DirectTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=10, locked_amount=0, recipient=app0.raiden.address, locksroot=EMPTY_MERKLE_ROOT, ) sign_and_inject( direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses): app0, app1, app2 = raiden_chain registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) secrethash = sha3(secret) gevent.sleep(.1) # wait for the messages # The secret hasn't been revealed yet channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1 channel.register_secret(channel_state2_1, secret, secrethash) # Close the channel # This needs to register the secrets on chain netting_channel_proxy = app2.raiden.chain.payment_channel( token_network_identifier, channel_state2_1.identifier, ) netting_channel_proxy.channel_close( registry_address, channel_state2_1.partner_state.balance_proof, ) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) assert_synced_channel_state( token_address, app1, deposit - amount, [], app2, deposit + amount, [], ) assert_synced_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_automatic_secret_registration(raiden_chain, token_addresses): app0, app1 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 100 identifier = 1 hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = hold_event_handler target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) gevent.sleep(1) # wait for the messages to be exchanged # Stop app0 to avoid sending the unlock app0.raiden.transport.stop() reveal_secret = RevealSecret( random.randint(0, UINT64_MAX), secret, ) app0.raiden.sign(reveal_secret) message_handler.MessageHandler().on_message(app1.raiden, reveal_secret) chain_state = views.state_from_app(app1) secrethash = sha3(secret) target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash] lock_expiration = target_task.target_state.transfer.lock.expiration wait_until_block(app1.raiden.chain, lock_expiration) assert app1.raiden.default_secret_registry.check_registered(secrethash)
def wait_for_saturated( connection_managers, registry_address, token_address, max_wait_blocks=80, ): chain = connection_managers[0].raiden.chain while max_wait_blocks > 0: saturated = saturated_count( connection_managers, registry_address, token_address, ) if saturated >= len(connection_managers): break wait_until_block(chain, chain.block_number() + 1) max_wait_blocks -= 1 return max_wait_blocks != 0
def test_automatic_secret_registration(raiden_chain, deposit, token_addresses, reveal_timeout): app0, app1 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 100 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) # Stop app0 to avoid sending the unlock app0.raiden.transport.stop() reveal_secret = RevealSecret( random.randint(0, UINT64_MAX), secret, ) app0.raiden.sign(reveal_secret) message_handler.on_message(app1.raiden, reveal_secret) chain_state = views.state_from_app(app1) secrethash = sha3(secret) target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash] lock_expiration = target_task.target_state.transfer.lock.expiration wait_until_block(app1.raiden.chain, lock_expiration) assert app1.raiden.default_secret_registry.check_registered(secrethash)
def test_payment_channel_proxy_basics( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=c1_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_proxy_2 = PaymentChannel( token_network=c2_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_2.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True assert channel_proxy_2.opened() is True # check the settlement timeouts assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN events = channel_filter.get_all_entries() assert len(events) == 1 # ChannelOpened # test deposits initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == 0 # actual deposit channel_proxy_1.set_total_deposit(10) events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelNewDeposit # balance proof by c2 transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) balance_proof.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof.serialize_bin(), )) # correct close c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True assert channel_proxy_2.closed() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelNewDeposit, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(c1_chain, c1_client.block_number() + TEST_SETTLE_TIMEOUT_MIN) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True assert channel_proxy_2.settled() is True events = channel_filter.get_all_entries() assert len(events) == 4 # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
def test_token_network_proxy_basics( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): # check settlement timeouts assert token_network_proxy.settlement_timeout_min( ) == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max( ) == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # instantiating a new channel - test basic assumptions assert c1_token_network_proxy.channel_exists_and_not_settled( c1_client.address, c2_client.address, ) is False channel_identifier = c1_token_network_proxy._call_and_check_result( 'latest', 'getChannelIdentifier', to_checksum_address(c1_client.address), to_checksum_address(c2_client.address), ) assert c1_token_network_proxy.channel_is_opened( c1_client.address, c2_client.address, channel_identifier, ) is False assert c1_token_network_proxy.channel_is_closed( c1_client.address, c2_client.address, channel_identifier, ) is False # test timeout limits with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN - 1, ) with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MAX + 1, ) # channel to self with pytest.raises(SamePeerAddress): c1_token_network_proxy.new_netting_channel( c1_client.address, TEST_SETTLE_TIMEOUT_MIN, ) # Channel is not open yet with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.set_total_deposit( 1, 1, c2_client.address, ) assert 'does not exist' in str(exc) # Channel is not open yet with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.close( 1, c2_client.address, EMPTY_HASH, 0, EMPTY_HASH, EMPTY_HASH, ) assert 'does not exist' in str(exc) # actually create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # multiple channels with the same peer are not allowed with pytest.raises(DuplicatedChannelError): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True assert c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True # channel is open. # deposit with no balance with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( channel_identifier, 101, c2_client.address, ) # no negative deposit with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( channel_identifier, -1, c2_client.address, ) # actual deposit c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) # balance proof by c2 transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) balance_proof.signature = encode_hex( eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof.serialize_bin(), )) # close with invalid signature with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=b'\x11' * 65, ) # correct close c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True # closing already closed channel with pytest.raises(RaidenRecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) with pytest.raises(RaidenRecoverableError) as exc: c2_token_network_proxy.set_total_deposit( channel_identifier, 20, c1_client.address, ) assert 'not in an open state' in str(exc) with pytest.raises(RaidenRecoverableError) as exc: c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert 'not in an open state' in str(exc) # update transfer wait_until_block(c1_chain, c1_chain.block_number() + TEST_SETTLE_TIMEOUT_MIN) # try to settle using incorrect data with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=1, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is False assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 - transferred_amount) assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount) with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) # No channel exists assert 'getChannelIdentifier returned 0' in str(exc)
def test_token_network_proxy_update_transfer( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): """Tests channel lifecycle, with `update_transfer` before settling""" token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, 10, ) # deposit to the channel initial_balance = 100 token_proxy.transfer(c1_client.address, initial_balance) token_proxy.transfer(c2_client.address, initial_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_balance c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) c2_token_network_proxy.set_total_deposit( channel_identifier, 10, c1_client.address, ) # balance proof signed by c1 transferred_amount_c1 = 1 transferred_amount_c2 = 3 balance_proof_c1 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount_c1, ) balance_proof_c1.signature = encode_hex( eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof_c1.serialize_bin(), )) # balance proof signed by c2 balance_proof_c2 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=2, chain_id=chain_id, transferred_amount=transferred_amount_c2, ) balance_proof_c2.signature = encode_hex( eth_sign( privkey=encode_hex(private_keys[2]), data=balance_proof_c2.serialize_bin(), )) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE, ) + decode_hex( balance_proof_c1.signature) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) assert 'not in a closed state' in str(exc) # close by c1 c1_token_network_proxy.close( channel_identifier=channel_identifier, partner=c2_client.address, balance_hash=decode_hex(balance_proof_c2.balance_hash), nonce=balance_proof_c2.nonce, additional_hash=decode_hex(balance_proof_c2.additional_hash), signature=decode_hex(balance_proof_c2.signature), ) # using invalid non-closing signature # Usual mistake when calling update Transfer - balance proof signature is missing in the data non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE, ) + decode_hex( balance_proof_c1.signature) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert 'cannot be settled before settlement window is over' in str(exc) wait_until_block(c1_chain, c1_chain.block_number() + 10) # settling with an invalid amount with pytest.raises(RaidenUnrecoverableError): c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=2, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) # proper settle c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert (token_proxy.balance_of( c2_client.address) == (initial_balance_c2 + transferred_amount_c1 - transferred_amount_c2)) assert (token_proxy.balance_of( c1_client.address) == (initial_balance_c1 + transferred_amount_c2 - transferred_amount_c1)) # Already settled with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.set_total_deposit( channel_identifier, 20, c1_client.address, ) assert 'getChannelIdentifier returned 0' in str(exc)
def test_token_network_proxy_update_transfer( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): """Tests channel lifecycle, with `update_transfer` before settling""" token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, 10, ) # deposit to the channel initial_balance = 100 token_proxy.transfer(c1_client.address, initial_balance) token_proxy.transfer(c2_client.address, initial_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_balance c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) c2_token_network_proxy.set_total_deposit( channel_identifier, 10, c1_client.address, ) # balance proof signed by c1 transferred_amount_c1 = 1 transferred_amount_c2 = 3 balance_proof_c1 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount_c1, ) balance_proof_c1.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof_c1.serialize_bin(), )) # balance proof signed by c2 balance_proof_c2 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=2, chain_id=chain_id, transferred_amount=transferred_amount_c2, ) balance_proof_c2.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[2]), data=balance_proof_c2.serialize_bin(), )) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE, ) + decode_hex(balance_proof_c1.signature) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) assert 'not in a closed state' in str(exc) # close by c1 c1_token_network_proxy.close( channel_identifier=channel_identifier, partner=c2_client.address, balance_hash=decode_hex(balance_proof_c2.balance_hash), nonce=balance_proof_c2.nonce, additional_hash=decode_hex(balance_proof_c2.additional_hash), signature=decode_hex(balance_proof_c2.signature), ) # using invalid non-closing signature # Usual mistake when calling update Transfer - balance proof signature is missing in the data non_closing_data = balance_proof_c1.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE, ) + decode_hex(balance_proof_c1.signature) non_closing_signature = eth_sign( privkey=encode_hex(c2_client.privkey), data=non_closing_data, ) c2_token_network_proxy.update_transfer( channel_identifier, c1_client.address, decode_hex(balance_proof_c1.balance_hash), balance_proof_c1.nonce, decode_hex(balance_proof_c1.additional_hash), decode_hex(balance_proof_c1.signature), non_closing_signature, ) with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert 'cannot be settled before settlement window is over' in str(exc) wait_until_block(c1_chain, c1_chain.block_number() + 10) # settling with an invalid amount with pytest.raises(RaidenUnrecoverableError): c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=2, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) # proper settle c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=EMPTY_HASH, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert (token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount_c1 - transferred_amount_c2)) assert (token_proxy.balance_of(c1_client.address) == (initial_balance_c1 + transferred_amount_c2 - transferred_amount_c1)) # Already settled with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.set_total_deposit( channel_identifier, 20, c1_client.address, ) assert 'getChannelIdentifier returned 0' in str(exc)
def test_start_end_attack(token_addresses, raiden_chain, deposit): """ An attacker can try to steal tokens from a hub or the last node in a path. The attacker needs to use two addresses (A1 and A2) and connect both to the hub H. Once connected a mediated transfer is initialized from A1 to A2 through H. Once the node A2 receives the mediated transfer the attacker uses the known secret and reveal to close and settle the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the token but for him to be unable to require the token A1.""" amount = 30 token = token_addresses[0] app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token, ) hold_event_handler = HoldOffChainSecretRequest() app2.raiden.raiden_event_handler = hold_event_handler # the attacker owns app0 and app2 and creates a transfer through app1 identifier = 1 target = app2.raiden.address secret = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) gevent.sleep(1) # wait for the messages to be exchanged attack_channel = get_channelstate(app2, app1, token_network_identifier) attack_transfer = None # TODO attack_contract = attack_channel.external_state.netting_channel.address hub_contract = ( get_channelstate(app1, app0, token_network_identifier) .external_state .netting_channel.address ) # the attacker can create a merkle proof of the locked transfer lock = attack_channel.partner_state.get_lock_by_secrethash(secrethash) unlock_proof = attack_channel.partner_state.compute_proof_for_lock(secret, lock) # start the settle counter attack_balance_proof = attack_transfer.to_balanceproof() attack_channel.netting_channel.channel_close(attack_balance_proof) # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1) # since the attacker knows the secret he can net the lock attack_channel.netting_channel.unlock( UnlockProofState(unlock_proof, attack_transfer.lock, secret), ) # XXX: verify that the secret was publicized # at this point the hub might not know the secret yet, and won't be able to # claim the token from the channel A1 - H # the attacker settles the contract app2.raiden.chain.next_block() attack_channel.netting_channel.settle(token, attack_contract) # at this point the attacker has the "stolen" funds attack_contract = app2.raiden.chain.token_hashchannel[token][attack_contract] assert attack_contract.participants[app2.raiden.address]['netted'] == deposit + amount assert attack_contract.participants[app1.raiden.address]['netted'] == deposit - amount # and the hub's channel A1-H doesn't hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract] assert hub_contract.participants[app0.raiden.address]['netted'] == deposit assert hub_contract.participants[app1.raiden.address]['netted'] == deposit # to mitigate the attack the Hub _needs_ to use a lower expiration for the # locked transfer between H-A2 than A1-H. For A2 to acquire the token # it needs to make the secret public in the blockchain so it publishes the # secret through an event and the Hub is able to require its funds app1.raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired its token hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract] assert hub_contract.participants[app0.raiden.address]['netted'] == deposit + amount assert hub_contract.participants[app1.raiden.address]['netted'] == deposit - amount
def test_secret_revealed_on_chain( raiden_chain, deposit, settle_timeout, token_addresses, retry_interval, ): """ A node must reveal the secret on-chain if it's known and the channel is closed. """ app0, app1, app2 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 target = app2.raiden.address secret = sha3(target) secrethash = sha3(secret) # Reveal the secret, but do not unlock it off-chain app1_hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = app1_hold_event_handler app1_hold_event_handler.hold_unlock_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, ) channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get(secrethash) msg = "The lock must be registered in unlocked locks since the secret is known" assert pending_lock is not None, msg # The channels are out-of-sync. app1 has sent the unlock, however we are # intercepting it and app2 has not received the updated balance proof # Close the channel. This must register the secret on chain channel_close_event = ContractSendChannelClose( channel_identifier=channel_state2_1.identifier, token_address=channel_state2_1.token_address, token_network_identifier=token_network_identifier, balance_proof=channel_state2_1.partner_state.balance_proof, ) app2.raiden.raiden_event_handler.on_raiden_event(app2.raiden, channel_close_event) settle_expiration = ( app0.raiden.chain.block_number() + settle_timeout + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS ) wait_until_block(app0.raiden.chain, settle_expiration) # TODO: # - assert on the transferred amounts on-chain (for settle and unlock) # The channel app0-app1 should continue with the protocol off-chain, once # the secret is released on-chain by app2 assert_synced_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ContractReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, )
def test_secret_revealed_on_chain( raiden_chain, deposit, settle_timeout, token_addresses, retry_interval, ): """ A node must reveal the secret on-chain if it's known and the channel is closed. """ app0, app1, app2 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 target = app2.raiden.address secret = sha3(target) secrethash = sha3(secret) # Reveal the secret, but do not unlock it off-chain app1_hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = app1_hold_event_handler app1_hold_event_handler.hold_unlock_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, ) channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get( secrethash) msg = "The lock must be registered in unlocked locks since the secret is known" assert pending_lock is not None, msg # The channels are out-of-sync. app1 has sent the unlock, however we are # intercepting it and app2 has not received the updated balance proof # Close the channel. This must register the secret on chain channel_close_event = ContractSendChannelClose( channel_identifier=channel_state2_1.identifier, token_address=channel_state2_1.token_address, token_network_identifier=token_network_identifier, balance_proof=channel_state2_1.partner_state.balance_proof, ) app2.raiden.raiden_event_handler.on_raiden_event(app2.raiden, channel_close_event) settle_expiration = (app0.raiden.chain.block_number() + settle_timeout + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS) wait_until_block(app0.raiden.chain, settle_expiration) # TODO: # - assert on the transferred amounts on-chain (for settle and unlock) # The channel app0-app1 should continue with the protocol off-chain, once # the secret is released on-chain by app2 assert_synced_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ContractReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, )
def test_received_lockedtransfer_closedchannel( raiden_network, reveal_timeout, token_addresses, deposit, ): app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one mediated transfer for the closed channel lock_amount = 10 payment_identifier = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synced_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_payment_channel_outdated_channel_close( token_network_proxy, private_keys, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) partner = privatekey_to_address(private_keys[0]) client = JSONRPCClient(web3, private_keys[1]) chain = BlockChainService(private_keys[1], client) token_network_proxy = TokenNetwork( jsonrpc_client=client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True # balance proof by c1 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=0, chain_id=chain_id, transferred_amount=0, ) balance_proof.signature = encode_hex( eth_sign( privkey=encode_hex(private_keys[0]), data=balance_proof.serialize_bin(), )) # correct close token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(chain, client.block_number() + TEST_SETTLE_TIMEOUT_MIN) token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=partner, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelClosed, ChannelSettled # Create a new channel with a different identifier # create a channel new_channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert new_channel_identifier is not None # create channel proxies channel_proxy_2 = PaymentChannel( token_network=token_network_proxy, channel_identifier=new_channel_identifier, contract_manager=contract_manager, ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened() is True with pytest.raises(ChannelOutdatedError): token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), )
def test_new_netting_contract(raiden_network, token_amount, settle_timeout): # pylint: disable=line-too-long,too-many-statements,too-many-locals app0, app1, app2 = raiden_network peer0_address = app0.raiden.address peer1_address = app1.raiden.address peer2_address = app2.raiden.address blockchain_service0 = app0.raiden.chain registry = app0.raiden.default_registry registry_address = app0.raiden.default_registry.address humantoken_path = get_contract_path('HumanStandardToken.sol') token_address = blockchain_service0.deploy_and_register_token( registry, contract_name='HumanStandardToken', contract_path=humantoken_path, constructor_parameters=(token_amount, 'raiden', 2, 'Rd'), ) token0 = blockchain_service0.token(token_address) for transfer_to in raiden_network[1:]: token0.transfer( privatekey_to_address(transfer_to.raiden.privkey), token_amount // len(raiden_network), ) manager0 = registry.manager_by_token(token_address) # sanity assert manager0.channels_addresses() == [] assert manager0.channels_by_participant(peer0_address) == [] assert manager0.channels_by_participant(peer1_address) == [] assert manager0.channels_by_participant(peer2_address) == [] # create one channel netting_address_01 = manager0.new_netting_channel( peer1_address, settle_timeout, ) exception = RuntimeError("Timeout while waiting for a new channel") with gevent.Timeout(seconds=10, exception=exception): waiting.wait_for_newchannel( app1.raiden, registry_address, token_address, app0.raiden.address, app1.raiden.alarm.wait_time, ) # check contract state netting_channel_01 = blockchain_service0.netting_channel(netting_address_01) assert netting_channel_01.can_transfer() is False # check channels channel_list = manager0.channels_addresses() assert sorted(channel_list[0]) == sorted([peer0_address, peer1_address]) assert manager0.channels_by_participant(peer0_address) == [netting_address_01] assert manager0.channels_by_participant(peer1_address) == [netting_address_01] assert manager0.channels_by_participant(peer2_address) == [] # create a duplicated channel with same participants while previous channel # is still open should throw an exception with pytest.raises(Exception): manager0.new_netting_channel( peer1_address, settle_timeout, ) # create other channel netting_address_02 = manager0.new_netting_channel( peer2_address, settle_timeout, ) netting_channel_02 = blockchain_service0.netting_channel(netting_address_02) assert netting_channel_02.can_transfer() is False channel_list = manager0.channels_addresses() expected_channels = [ sorted([peer0_address, peer1_address]), sorted([peer0_address, peer2_address]), ] for channel in channel_list: assert sorted(channel) in expected_channels result0 = sorted(manager0.channels_by_participant(peer0_address)) result1 = sorted([netting_address_01, netting_address_02]) assert result0 == result1 assert manager0.channels_by_participant(peer1_address) == [netting_address_01] assert manager0.channels_by_participant(peer2_address) == [netting_address_02] # deposit without approve should fail netting_channel_01.set_total_deposit(100) assert netting_channel_01.can_transfer() is False assert netting_channel_02.can_transfer() is False assert netting_channel_01.detail()['our_balance'] == 0 assert netting_channel_02.detail()['our_balance'] == 0 # single-funded channel app0.raiden.chain.token(token_address).approve(netting_address_01, 100) netting_channel_01.set_total_deposit(100) assert netting_channel_01.can_transfer() is True assert netting_channel_02.can_transfer() is False assert netting_channel_01.detail()['our_balance'] == 100 assert netting_channel_02.detail()['our_balance'] == 0 # double-funded channel app0.raiden.chain.token(token_address).approve(netting_address_02, 70) netting_channel_02.set_total_deposit(70) assert netting_channel_01.can_transfer() is True assert netting_channel_02.can_transfer() is True assert netting_channel_02.detail()['our_balance'] == 70 assert netting_channel_02.detail()['partner_balance'] == 0 app2.raiden.chain.token(token_address).approve(netting_address_02, 130) app2.raiden.chain.netting_channel(netting_address_02).set_total_deposit(130) assert netting_channel_01.can_transfer() is True assert netting_channel_02.can_transfer() is True assert netting_channel_02.detail()['our_balance'] == 70 assert netting_channel_02.detail()['partner_balance'] == 130 wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + 2) RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address) waiting.wait_for_settle( app1.raiden, registry_address, token_address, [netting_address_01], app1.raiden.alarm.wait_time, ) with pytest.raises(AddressWithoutCode): netting_channel_01.closed() with pytest.raises(AddressWithoutCode): netting_channel_01.opened() # open channel with same peer again netting_address_01_reopened = manager0.new_netting_channel( peer1_address, settle_timeout, ) netting_channel_01_reopened = blockchain_service0.netting_channel(netting_address_01_reopened) assert netting_channel_01_reopened.opened() != 0 assert netting_address_01_reopened in manager0.channels_by_participant(peer0_address) assert netting_address_01 not in manager0.channels_by_participant(peer0_address) app0.raiden.chain.token(token_address).approve(netting_address_01_reopened, 100) netting_channel_01_reopened.set_total_deposit(100) assert netting_channel_01_reopened.opened() != 0
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_protocol): node1, node2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(node1), node1.raiden.default_registry.address, token_address, ) api1 = RaidenAPI(node1.raiden) api2 = RaidenAPI(node2.raiden) registry_address = node1.raiden.default_registry.address # nodes don't have a channel, so they are not healthchecking assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN assert not api1.get_channel_list(registry_address, token_address, api2.address) # Make sure invalid arguments to get_channel_list are caught with pytest.raises(UnknownTokenAddress): api1.get_channel_list( registry_address=registry_address, token_address=None, partner_address=api2.address, ) # open is a synchronous api api1.channel_open(node1.raiden.default_registry.address, token_address, api2.address) channels = api1.get_channel_list(registry_address, token_address, api2.address) assert len(channels) == 1 channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED event_list1 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert any( ( event['event'] == ChannelEvent.OPENED and is_same_address( event['args']['participant1'], to_normalized_address(api1.address), ) and is_same_address( event['args']['participant2'], to_normalized_address(api2.address), ) ) for event in event_list1 ) token_events = api1.get_blockchain_events_token_network( token_address, ) assert token_events[0]['event'] == ChannelEvent.OPENED registry_address = api1.raiden.default_registry.address # Load the new state with the deposit api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit with pytest.raises(DepositMismatch): api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED assert channel.get_balance(channel12.our_state, channel12.partner_state) == deposit assert channel12.our_state.contract_balance == deposit assert api1.get_channel_list(registry_address, token_address, api2.address) == [channel12] # there is a channel open, they must be healthchecking each other assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE event_list2 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert any( ( event['event'] == ChannelEvent.DEPOSIT and is_same_address( event['args']['participant'], to_normalized_address(api1.address), ) and event['args']['total_deposit'] == deposit ) for event in event_list2 ) api1.channel_close(registry_address, token_address, api2.address) # Load the new state with the channel closed channel12 = get_channelstate(node1, node2, token_network_identifier) event_list3 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert len(event_list3) > len(event_list2) assert any( ( event['event'] == ChannelEvent.CLOSED and is_same_address( event['args']['closing_participant'], to_normalized_address(api1.address), ) ) for event in event_list3 ) assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED settlement_block = ( channel12.close_transaction.finished_block_number + channel12.settle_timeout + 10 # arbitrary number of additional blocks, used to wait for the settle() call ) wait_until_block(node1.raiden.chain, settlement_block + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS) state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) assert must_contain_entry(state_changes, ContractReceiveChannelSettled, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel12.identifier, })
def test_participant_selection(raiden_network, token_addresses): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address, token_address, 100, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) # wait some blocks to let the network connect wait_blocks = 15 for _ in range(wait_blocks): for app in raiden_network: wait_until_block( app.raiden.chain, app.raiden.chain.block_number() + 1, ) connection_managers = [ app.raiden.connection_manager_for_token( registry_address, token_address, ) for app in raiden_network ] def open_channels_count(connection_managers_): return [ connection_manager.open_channels for connection_manager in connection_managers_ ] assert all(open_channels_count(connection_managers)) def not_saturated(connection_managers_): return [ 1 for connection_manager_ in connection_managers_ if len(connection_manager_.open_channels) < connection_manager_.initial_channel_target ] chain = raiden_network[-1].raiden.chain max_wait = 12 while not_saturated(connection_managers) and max_wait > 0: wait_until_block(chain, chain.block_number() + 1) max_wait -= 1 assert not not_saturated(connection_managers) # Ensure unpartitioned network addresses = [app.raiden.address for app in raiden_network] for connection_manager in connection_managers: assert all( connection_manager.channelgraph.has_path( connection_manager.raiden.address, address, ) for address in addresses) # average channel count acc = (sum( len(connection_manager.open_channels) for connection_manager in connection_managers) / len(connection_managers)) try: # FIXME: depending on the number of channels, this will fail, due to weak # selection algorithm # https://github.com/raiden-network/raiden/issues/576 assert not any( len(connection_manager.open_channels) > 2 * acc for connection_manager in connection_managers) except AssertionError: pass # create a transfer to the leaving node, so we have a channel to settle sender = raiden_network[-1].raiden receiver = raiden_network[0].raiden registry_address = sender.raiden.default_registry.address # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] assert receiver_channel.external_state.opened_block != 0 assert not receiver_channel.received_transfers # assert there is a direct channel sender -> receiver sender_channel = RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=receiver.address, ) assert len(sender_channel) == 1 sender_channel = sender_channel[0] assert sender_channel.can_transfer assert sender_channel.external_state.opened_block != 0 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, 1, receiver.address, ) # now receiver has a transfer assert len(receiver_channel.received_transfers) # test `leave()` method connection_manager = connection_managers[0] before = len(connection_manager.receiving_channels) timeout = (connection_manager.min_settle_blocks * connection_manager.raiden.chain.estimate_blocktime() * 5) assert timeout > 0 with gevent.timeout.Timeout(timeout): try: RaidenAPI(raiden_network[0].raiden).token_network_leave( registry_address, token_address, ) except gevent.timeout.Timeout: log.error('timeout while waiting for leave') before_block = connection_manager.raiden.chain.block_number() wait_blocks = connection_manager.min_settle_blocks + 10 wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) assert connection_manager.raiden.chain.block_number >= before_block + wait_blocks wait_until_block( receiver.chain, before_block + wait_blocks, ) while receiver_channel.state != CHANNEL_STATE_SETTLED: gevent.sleep(receiver.alarm.wait_time) after = len(connection_manager.receiving_channels) assert before > after assert after == 0
def test_token_network_proxy_basics( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): # check settlement timeouts assert token_network_proxy.settlement_timeout_min() == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max() == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # instantiating a new channel - test basic assumptions assert c1_token_network_proxy.channel_exists_and_not_settled( c1_client.address, c2_client.address, ) is False channel_identifier = c1_token_network_proxy._call_and_check_result( 'latest', 'getChannelIdentifier', to_checksum_address(c1_client.address), to_checksum_address(c2_client.address), ) assert c1_token_network_proxy.channel_is_opened( c1_client.address, c2_client.address, channel_identifier, ) is False assert c1_token_network_proxy.channel_is_closed( c1_client.address, c2_client.address, channel_identifier, ) is False # test timeout limits with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN - 1, ) with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MAX + 1, ) # channel to self with pytest.raises(SamePeerAddress): c1_token_network_proxy.new_netting_channel( c1_client.address, TEST_SETTLE_TIMEOUT_MIN, ) # Channel is not open yet with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.set_total_deposit( 1, 1, c2_client.address, ) assert 'does not exist' in str(exc) # Channel is not open yet with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.close( 1, c2_client.address, EMPTY_HASH, 0, EMPTY_HASH, EMPTY_HASH, ) assert 'does not exist' in str(exc) # actually create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # multiple channels with the same peer are not allowed with pytest.raises(DuplicatedChannelError): c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True assert c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True # channel is open. # deposit with no balance with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( channel_identifier, 101, c2_client.address, ) # no negative deposit with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( channel_identifier, -1, c2_client.address, ) # actual deposit c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) # balance proof by c2 transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) balance_proof.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof.serialize_bin(), )) # close with invalid signature with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=b'\x11' * 65, ) # correct close c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is True # closing already closed channel with pytest.raises(RaidenRecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) with pytest.raises(RaidenRecoverableError) as exc: c2_token_network_proxy.set_total_deposit( channel_identifier, 20, c1_client.address, ) assert 'not in an open state' in str(exc) with pytest.raises(RaidenRecoverableError) as exc: c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert 'not in an open state' in str(exc) # update transfer wait_until_block(c1_chain, c1_chain.block_number() + TEST_SETTLE_TIMEOUT_MIN) # try to settle using incorrect data with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=1, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert c1_token_network_proxy.channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, ) is False assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 - transferred_amount) assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount) with pytest.raises(RaidenUnrecoverableError) as exc: c1_token_network_proxy.set_total_deposit( channel_identifier, 10, c2_client.address, ) # No channel exists assert 'getChannelIdentifier returned 0' in str(exc)
def test_payment_channel_outdated_channel_close( token_network_proxy, private_keys, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) partner = privatekey_to_address(private_keys[0]) client = JSONRPCClient(web3, private_keys[1]) chain = BlockChainService(private_keys[1], client) token_network_proxy = TokenNetwork( jsonrpc_client=client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True # balance proof by c1 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=0, chain_id=chain_id, transferred_amount=0, ) balance_proof.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[0]), data=balance_proof.serialize_bin(), )) # correct close token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(chain, client.block_number() + TEST_SETTLE_TIMEOUT_MIN) token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=partner, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelClosed, ChannelSettled # Create a new channel with a different identifier # create a channel new_channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert new_channel_identifier is not None # create channel proxies channel_proxy_2 = PaymentChannel( token_network=token_network_proxy, channel_identifier=new_channel_identifier, contract_manager=contract_manager, ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened() is True with pytest.raises(ChannelOutdatedError): token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), )
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_config): node1, node2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(node1), node1.raiden.default_registry.address, token_address, ) api1 = RaidenAPI(node1.raiden) api2 = RaidenAPI(node2.raiden) registry_address = node1.raiden.default_registry.address # nodes don't have a channel, so they are not healthchecking assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN assert not api1.get_channel_list(registry_address, token_address, api2.address) # open is a synchronous api api1.channel_open(node1.raiden.default_registry.address, token_address, api2.address) channels = api1.get_channel_list(registry_address, token_address, api2.address) assert len(channels) == 1 channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED event_list1 = api1.get_channel_events( token_address, channel12.partner_state.address, channel12.open_transaction.finished_block_number, ) assert any( ( event['event'] == EVENT_CHANNEL_OPENED and is_same_address( event['args']['participant1'], to_normalized_address(api1.address), ) and is_same_address( event['args']['participant2'], to_normalized_address(api2.address), ) ) for event in event_list1 ) token_events = api1.get_token_network_events( token_address, channel12.open_transaction.finished_block_number, ) assert token_events[0]['event'] == EVENT_CHANNEL_OPENED registry_address = api1.raiden.default_registry.address # Load the new state with the deposit api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) # let's make sure it's idempotent api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED assert channel.get_balance(channel12.our_state, channel12.partner_state) == deposit assert channel12.our_state.contract_balance == deposit assert api1.get_channel_list(registry_address, token_address, api2.address) == [channel12] # there is a channel open, they must be healthchecking each other assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE event_list2 = api1.get_channel_events( token_address, channel12.partner_state.address, channel12.open_transaction.finished_block_number, ) assert any( ( event['event'] == EVENT_CHANNEL_DEPOSIT and is_same_address( event['args']['participant'], to_normalized_address(api1.address), ) and event['args']['total_deposit'] == deposit ) for event in event_list2 ) api1.channel_close(registry_address, token_address, api2.address) # Load the new state with the channel closed channel12 = get_channelstate(node1, node2, token_network_identifier) event_list3 = api1.get_channel_events( token_address, channel12.partner_state.address, channel12.open_transaction.finished_block_number, ) assert len(event_list3) > len(event_list2) assert any( ( event['event'] == EVENT_CHANNEL_CLOSED and is_same_address( event['args']['closing_participant'], to_normalized_address(api1.address), ) ) for event in event_list3 ) assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED settlement_block = ( channel12.close_transaction.finished_block_number + channel12.settle_timeout + 10 # arbitrary number of additional blocks, used to wait for the settle() call ) wait_until_block(node1.raiden.chain, settlement_block) # Load the new state with the channel settled channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
def test_query_events( raiden_chain, token_addresses, deposit, settle_timeout, retry_timeout, contract_manager, ): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) token_network_address = app0.raiden.default_registry.get_token_network(token_address) manager0 = app0.raiden.chain.token_network(token_network_address) channelcount0 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) events = get_token_network_registry_events( chain=app0.raiden.chain, token_network_registry_address=registry_address, contract_manager=contract_manager, events=ALL_EVENTS, ) assert must_have_event( events, { 'event': EVENT_TOKEN_NETWORK_CREATED, 'args': { 'token_network_address': to_checksum_address(manager0.address), 'token_address': to_checksum_address(token_address), }, }, ) events = get_token_network_registry_events( chain=app0.raiden.chain, token_network_registry_address=app0.raiden.default_registry.address, contract_manager=contract_manager, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events RaidenAPI(app0.raiden).channel_open( registry_address, token_address, app1.raiden.address, ) wait_both_channel_open(app0, app1, registry_address, token_address, retry_timeout) events = get_token_network_events( chain=app0.raiden.chain, token_network_address=manager0.address, contract_manager=contract_manager, events=ALL_EVENTS, ) _event = must_have_event( events, { 'event': ChannelEvent.OPENED, 'args': { 'participant1': to_checksum_address(app0.raiden.address), 'participant2': to_checksum_address(app1.raiden.address), 'settle_timeout': settle_timeout, }, }, ) assert _event channel_id = _event['args']['channel_identifier'] events = get_token_network_events( chain=app0.raiden.chain, token_network_address=manager0.address, contract_manager=contract_manager, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events # channel is created but not opened and without funds channelcount1 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) assert channelcount0 + 1 == channelcount1 assert_synced_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).set_total_channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) all_netting_channel_events = get_all_netting_channel_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=app0.raiden.contract_manager, ) deposit_events = get_netting_channel_deposit_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=contract_manager, ) total_deposit_event = { 'event': ChannelEvent.DEPOSIT, 'args': { 'participant': to_checksum_address(app0.raiden.address), 'total_deposit': deposit, 'channel_identifier': channel_id, }, } assert must_have_event(deposit_events, total_deposit_event) assert must_have_event(all_netting_channel_events, total_deposit_event) RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) all_netting_channel_events = get_all_netting_channel_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=app0.raiden.contract_manager, ) closed_events = get_netting_channel_closed_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=contract_manager, ) closed_event = { 'event': ChannelEvent.CLOSED, 'args': { 'channel_identifier': channel_id, 'closing_participant': to_checksum_address(app0.raiden.address), }, } assert must_have_event(closed_events, closed_event) assert must_have_event(all_netting_channel_events, closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5 wait_until_block(app0.raiden.chain, settle_expiration) all_netting_channel_events = get_all_netting_channel_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=app0.raiden.contract_manager, ) settled_events = get_netting_channel_settled_events( chain=app0.raiden.chain, token_network_address=token_network_identifier, netting_channel_identifier=channel_id, contract_manager=contract_manager, ) settled_event = { 'event': ChannelEvent.SETTLED, 'args': { 'channel_identifier': channel_id, }, } assert must_have_event(settled_events, settled_event) assert must_have_event(all_netting_channel_events, settled_event)
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses): app0, app1, app2 = raiden_chain registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) secrethash = sha3(secret) gevent.sleep(.1) # wait for the messages channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) # the secret hasn't been revealed yet (through messages) assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1 proofs = list(channel.get_known_unlocks(channel_state2_1.our_state)) assert not proofs channel.register_secret(channel_state2_1, secret, secrethash) # Close the channel netting_channel_proxy = app2.raiden.chain.netting_channel( channel_state2_1.identifier) netting_channel_proxy.channel_close( registry_address, channel_state2_1.partner_state.balance_proof, ) # Reveal the secret through the blockchain (this needs to emit the # SecretRevealed event) for unlock_proof in channel.get_known_unlocks( channel_state2_1.partner_state): netting_channel_proxy.unlock(unlock_proof) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) assert_synched_channel_state( token_address, app1, deposit - amount, [], app2, deposit + amount, [], ) assert_synched_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_participant_selection(raiden_network, token_addresses, skip_if_tester): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address, token_address, 100, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] with gevent.Timeout( 120, AssertionError('Unsaturated connection managers', unsaturated_connection_managers), ): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle sender = raiden_network[-1].raiden receiver = raiden_network[0].raiden registry_address = sender.default_registry.address # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] # assert there is a direct channel sender -> receiver sender_channel = RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=receiver.address, ) assert len(sender_channel) == 1 sender_channel = sender_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): RaidenAPI(raiden_network[0].raiden).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert receiver_channel[0].settle_transaction is not None
def test_payment_channel_proxy_basics( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=c1_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_proxy_2 = PaymentChannel( token_network=c2_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_2.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True assert channel_proxy_2.opened() is True # check the settlement timeouts assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN events = channel_filter.get_all_entries() assert len(events) == 1 # ChannelOpened # test deposits initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == 0 # actual deposit channel_proxy_1.set_total_deposit(10) events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelNewDeposit # balance proof by c2 transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) balance_proof.signature = encode_hex( eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof.serialize_bin(), )) # correct close c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True assert channel_proxy_2.closed() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelNewDeposit, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(c1_chain, c1_client.block_number() + TEST_SETTLE_TIMEOUT_MIN) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True assert channel_proxy_2.settled() is True events = channel_filter.get_all_entries() assert len( events ) == 4 # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses): app0, app1, app2 = raiden_chain registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) hold_event_handler = HoldOffChainSecretRequest() app2.raiden.raiden_event_handler = hold_event_handler amount = 10 identifier = 1 target = app2.raiden.address secret = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secret) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) gevent.sleep(.1) # wait for the messages # The secret hasn't been revealed yet channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1 channel.register_offchain_secret(channel_state2_1, secret, secrethash) # Close the channel # This needs to register the secrets on chain netting_channel_proxy = app2.raiden.chain.payment_channel( token_network_identifier, channel_state2_1.identifier, ) netting_channel_proxy.channel_close( registry_address, channel_state2_1.partner_state.balance_proof, ) settle_expiration = ( app0.raiden.chain.block_number() + settle_timeout + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS ) wait_until_block(app0.raiden.chain, settle_expiration) assert_synced_channel_state( token_address, app1, deposit - amount, [], app2, deposit + amount, [], ) assert_synced_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_config): node1, node2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(node1), node1.raiden.default_registry.address, token_address, ) api1 = RaidenAPI(node1.raiden) api2 = RaidenAPI(node2.raiden) registry_address = node1.raiden.default_registry.address # nodes don't have a channel, so they are not healthchecking assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN assert not api1.get_channel_list(registry_address, token_address, api2.address) # open is a synchronous api api1.channel_open(node1.raiden.default_registry.address, token_address, api2.address) channels = api1.get_channel_list(registry_address, token_address, api2.address) assert len(channels) == 1 channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED event_list1 = api1.get_channel_events( channel12.identifier, channel12.open_transaction.finished_block_number, ) assert event_list1 == [] token_events = api1.get_token_network_events( token_address, channel12.open_transaction.finished_block_number, ) assert token_events[0]['event'] == EVENT_CHANNEL_NEW registry_address = api1.raiden.default_registry.address # Load the new state with the deposit api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) # let's make sure it's idempotent api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED assert channel.get_balance(channel12.our_state, channel12.partner_state) == deposit assert channel12.our_state.contract_balance == deposit assert api1.get_channel_list(registry_address, token_address, api2.address) == [channel12] # there is a channel open, they must be healthchecking each other assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE event_list2 = api1.get_channel_events( channel12.identifier, channel12.open_transaction.finished_block_number, ) assert any( ( event['event'] == EVENT_CHANNEL_NEW_BALANCE and is_same_address( event['args']['registry_address'], to_normalized_address(registry_address), ) and is_same_address( event['args']['participant'], to_normalized_address(api1.address), ) ) for event in event_list2 ) api1.channel_close(registry_address, token_address, api2.address) # Load the new state with the channel closed channel12 = get_channelstate(node1, node2, token_network_identifier) event_list3 = api1.get_channel_events( channel12.identifier, channel12.open_transaction.finished_block_number, ) assert len(event_list3) > len(event_list2) assert any( ( event['event'] == EVENT_CHANNEL_CLOSED and is_same_address( event['args']['registry_address'], to_normalized_address(registry_address), ) and is_same_address( event['args']['closing_address'], to_normalized_address(api1.address), ) ) for event in event_list3 ) assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED settlement_block = ( channel12.close_transaction.finished_block_number + channel12.settle_timeout + 10 # arbitrary number of additional blocks, used to wait for the settle() call ) wait_until_block(node1.raiden.chain, settlement_block) # Load the new state with the channel settled channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_config): node1, node2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(node1), node1.raiden.default_registry.address, token_address, ) api1 = RaidenAPI(node1.raiden) api2 = RaidenAPI(node2.raiden) registry_address = node1.raiden.default_registry.address # nodes don't have a channel, so they are not healthchecking assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN assert not api1.get_channel_list(registry_address, token_address, api2.address) # open is a synchronous api api1.channel_open(node1.raiden.default_registry.address, token_address, api2.address) channels = api1.get_channel_list(registry_address, token_address, api2.address) assert len(channels) == 1 channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED event_list1 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert any((event['event'] == ChannelEvent.OPENED and is_same_address( event['args']['participant1'], to_normalized_address(api1.address), ) and is_same_address( event['args']['participant2'], to_normalized_address(api2.address), )) for event in event_list1) token_events = api1.get_blockchain_events_token_network(token_address, ) assert token_events[0]['event'] == ChannelEvent.OPENED registry_address = api1.raiden.default_registry.address # Load the new state with the deposit api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit with pytest.raises(DepositMismatch): api1.set_total_channel_deposit( registry_address, token_address, api2.address, deposit, ) channel12 = get_channelstate(node1, node2, token_network_identifier) assert channel.get_status(channel12) == CHANNEL_STATE_OPENED assert channel.get_balance(channel12.our_state, channel12.partner_state) == deposit assert channel12.our_state.contract_balance == deposit assert api1.get_channel_list(registry_address, token_address, api2.address) == [channel12] # there is a channel open, they must be healthchecking each other assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE event_list2 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert any((event['event'] == ChannelEvent.DEPOSIT and is_same_address( event['args']['participant'], to_normalized_address(api1.address), ) and event['args']['total_deposit'] == deposit) for event in event_list2) api1.channel_close(registry_address, token_address, api2.address) # Load the new state with the channel closed channel12 = get_channelstate(node1, node2, token_network_identifier) event_list3 = api1.get_blockchain_events_channel( token_address, channel12.partner_state.address, ) assert len(event_list3) > len(event_list2) assert any((event['event'] == ChannelEvent.CLOSED and is_same_address( event['args']['closing_participant'], to_normalized_address(api1.address), )) for event in event_list3) assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED settlement_block = ( channel12.close_transaction.finished_block_number + channel12.settle_timeout + 10 # arbitrary number of additional blocks, used to wait for the settle() call ) wait_until_block(node1.raiden.chain, settlement_block) state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) assert must_contain_entry( state_changes, ContractReceiveChannelSettled, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel12.identifier, })
def test_participant_selection(raiden_network, token_addresses, skip_if_tester): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address, token_address, 100, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] assert wait_for_saturated( connection_managers, registry_address, token_address, ) is True assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle sender = raiden_network[-1].raiden receiver = raiden_network[0].raiden registry_address = sender.default_registry.address # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] # assert there is a direct channel sender -> receiver sender_channel = RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=receiver.address, ) assert len(sender_channel) == 1 sender_channel = sender_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): RaidenAPI(raiden_network[0].raiden).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert receiver_channel[0].settle_transaction is not None
def test_start_end_attack(token_addresses, raiden_chain, deposit): """ An attacker can try to steal tokens from a hub or the last node in a path. The attacker needs to use two addresses (A1 and A2) and connect both to the hub H. Once connected a mediated transfer is initialized from A1 to A2 through H. Once the node A2 receives the mediated transfer the attacker uses the known secret and reveal to close and settle the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the token but for him to be unable to require the token A1.""" amount = 30 token = token_addresses[0] app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token, ) # the attacker owns app0 and app2 and creates a transfer through app1 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) secrethash = sha3(secret) attack_channel = get_channelstate(app2, app1, token_network_identifier) attack_transfer = None # TODO attack_contract = attack_channel.external_state.netting_channel.address hub_contract = (get_channelstate( app1, app0, token_network_identifier).external_state.netting_channel.address) # the attacker can create a merkle proof of the locked transfer lock = attack_channel.partner_state.get_lock_by_secrethash(secrethash) unlock_proof = attack_channel.partner_state.compute_proof_for_lock( secret, lock) # start the settle counter attack_balance_proof = attack_transfer.to_balanceproof() attack_channel.netting_channel.channel_close(attack_balance_proof) # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1) # since the attacker knows the secret he can net the lock attack_channel.netting_channel.unlock( UnlockProofState(unlock_proof, attack_transfer.lock, secret), ) # XXX: verify that the secret was publicized # at this point the hub might not know the secret yet, and won't be able to # claim the token from the channel A1 - H # the attacker settles the contract app2.raiden.chain.next_block() attack_channel.netting_channel.settle(token, attack_contract) # at this point the attacker has the "stolen" funds attack_contract = app2.raiden.chain.token_hashchannel[token][ attack_contract] assert attack_contract.participants[ app2.raiden.address]['netted'] == deposit + amount assert attack_contract.participants[ app1.raiden.address]['netted'] == deposit - amount # and the hub's channel A1-H doesn't hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract] assert hub_contract.participants[app0.raiden.address]['netted'] == deposit assert hub_contract.participants[app1.raiden.address]['netted'] == deposit # to mitigate the attack the Hub _needs_ to use a lower expiration for the # locked transfer between H-A2 than A1-H. For A2 to acquire the token # it needs to make the secret public in the blockchain so it publishes the # secret through an event and the Hub is able to require its funds app1.raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired its token hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract] assert hub_contract.participants[ app0.raiden.address]['netted'] == deposit + amount assert hub_contract.participants[ app1.raiden.address]['netted'] == deposit - amount
def test_participant_selection(raiden_network, token_addresses): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, ) # Test invalid argument values with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=-1, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=2, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=-1, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] with gevent.Timeout( 120, AssertionError('Unsaturated connection managers', unsaturated_connection_managers), ): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle for app in raiden_network: sender = app.raiden sender_channel = next(( channel_state for channel_state in RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, ) if channel_state.our_state.contract_balance > 0 and channel_state.partner_state.contract_balance > 0 ), None) # choose a fully funded channel from sender if sender_channel: break registry_address = sender.default_registry.address receiver = next( app.raiden for app in raiden_network if app.raiden.address == sender_channel.partner_state.address ) # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): # sender leaves the network RaidenAPI(sender).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) # because of timing, channel may already have been cleaned assert not receiver_channel or receiver_channel[0].settle_transaction is not None
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout, retry_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) manager0 = app0.raiden.default_registry.token_network_by_token( token_address) channelcount0 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) events = get_token_network_registry_events( app0.raiden.chain, registry_address, events=ALL_EVENTS, ) assert must_have_event( events, { 'event': EVENT_TOKEN_NETWORK_CREATED, 'args': { 'token_network_address': to_checksum_address(manager0.address), 'token_address': to_checksum_address(token_address), }, }, ) events = get_token_network_registry_events( app0.raiden.chain, app0.raiden.default_registry.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events RaidenAPI(app0.raiden).channel_open( registry_address, token_address, app1.raiden.address, ) events = get_token_network_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, ) _event = must_have_event( events, { 'event': EVENT_CHANNEL_OPENED, 'args': { 'participant1': to_checksum_address(app0.raiden.address), 'participant2': to_checksum_address(app1.raiden.address), 'settle_timeout': settle_timeout, }, }, ) assert _event channel_id = _event['args']['channel_identifier'] events = get_token_network_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events # channel is created but not opened and without funds channelcount1 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) assert channelcount0 + 1 == channelcount1 assert_synched_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).set_total_channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) deposit_events = get_netting_channel_deposit_events( app0.raiden.chain, token_network_identifier, channel_id, ) total_deposit_event = { 'event': EVENT_CHANNEL_DEPOSIT, 'args': { 'participant': to_checksum_address(app0.raiden.address), 'total_deposit': deposit, 'channel_identifier': channel_id, }, } assert must_have_event(deposit_events, total_deposit_event) assert must_have_event(all_netting_channel_events, total_deposit_event) RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) closed_events = get_netting_channel_closed_events( app0.raiden.chain, token_network_identifier, channel_id, ) closed_event = { 'event': EVENT_CHANNEL_CLOSED, 'args': { 'channel_identifier': channel_id, 'closing_participant': to_checksum_address(app0.raiden.address), }, } assert must_have_event(closed_events, closed_event) assert must_have_event(all_netting_channel_events, closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5 wait_until_block(app0.raiden.chain, settle_expiration) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) settled_events = get_netting_channel_settled_events( app0.raiden.chain, token_network_identifier, channel_id, ) settled_event = { 'event': EVENT_CHANNEL_SETTLED, 'args': { 'channel_identifier': channel_id, }, } assert must_have_event(settled_events, settled_event) assert must_have_event(all_netting_channel_events, settled_event)
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout, retry_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) manager0 = app0.raiden.default_registry.manager_by_token(token_address) channelcount0 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) events = get_all_registry_events( app0.raiden.chain, registry_address, events=ALL_EVENTS, from_block=0, to_block='latest', ) assert len(events) == 1 assert events[0]['event'] == EVENT_TOKEN_ADDED assert event_dicts_are_equal( events[0]['args'], { 'registry_address': to_normalized_address(registry_address), 'channel_manager_address': to_normalized_address(manager0.address), 'token_address': to_normalized_address(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 channel_address = RaidenAPI(app0.raiden).channel_open( registry_address, token_address, app1.raiden.address, ) gevent.sleep(retry_timeout * 2) 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 events[0]['event'] == EVENT_CHANNEL_NEW assert event_dicts_are_equal( events[0]['args'], { 'registry_address': to_normalized_address(registry_address), 'settle_timeout': settle_timeout, 'netting_channel': to_normalized_address(channel_address), 'participant1': to_normalized_address(app0.raiden.address), 'participant2': to_normalized_address(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 # channel is created but not opened and without funds channelcount1 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) assert channelcount0 + 1 == channelcount1 assert_synched_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).set_total_channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) gevent.sleep(retry_timeout * 2) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)], ) assert len(all_netting_channel_events) == 1 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_NEW_BALANCE new_balance_event = { 'registry_address': to_normalized_address(registry_address), 'token_address': to_normalized_address(token_address), 'participant': to_normalized_address(app0.raiden.address), 'balance': deposit, 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], new_balance_event) assert event_dicts_are_equal(events[0]['args'], new_balance_event) RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) gevent.sleep(retry_timeout * 2) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)], ) assert len(all_netting_channel_events) == 2 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_CLOSED closed_event = { 'registry_address': to_normalized_address(registry_address), 'closing_address': to_normalized_address(app0.raiden.address), 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], closed_event) assert event_dicts_are_equal(events[0]['args'], closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5 wait_until_block(app0.raiden.chain, settle_expiration) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)], ) assert len(all_netting_channel_events) == 3 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_SETTLED settled_event = { 'registry_address': to_normalized_address(registry_address), 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], settled_event) assert event_dicts_are_equal(events[0]['args'], settled_event)