def test_mediated_transfer_events(raiden_network, number_of_nodes, token_addresses, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) amount = 10 mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes, ) def test_initiator_events(): initiator_blockevents = app0.raiden.wal.storage.get_events_by_identifier( from_identifier=0, to_identifier='latest', ) initiator_events = [blocknumber_event[1] for blocknumber_event in initiator_blockevents] return ( must_contain_entry(initiator_events, SendRevealSecret, {}) and must_contain_entry(initiator_events, EventUnlockSuccess, {}) ) assert wait_until(test_initiator_events, network_wait) def test_mediator_events(): mediator_blockevents = app1.raiden.wal.storage.get_events_by_identifier( from_identifier=0, to_identifier='latest', ) mediator_events = [blocknumber_event[1] for blocknumber_event in mediator_blockevents] return ( must_contain_entry(mediator_events, EventUnlockSuccess, {}) and must_contain_entry(mediator_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_mediator_events, network_wait) def test_target_events(): target_blockevents = app2.raiden.wal.storage.get_events_by_identifier( from_identifier=0, to_identifier='latest', ) target_events = [blocknumber_event[1] for blocknumber_event in target_blockevents] return ( must_contain_entry(target_events, SendSecretRequest, {}) and must_contain_entry(target_events, SendRevealSecret, {}) and must_contain_entry(target_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_target_events, network_wait)
def test_mediated_transfer_events(raiden_network, number_of_nodes, token_addresses, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) amount = 10 mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes, ) def test_initiator_events(): initiator_events = app0.raiden.wal.storage.get_events() return ( must_contain_entry(initiator_events, SendSecretReveal, {}) and must_contain_entry(initiator_events, EventUnlockSuccess, {}) ) assert wait_until(test_initiator_events, network_wait) def test_mediator_events(): mediator_events = app1.raiden.wal.storage.get_events() return ( must_contain_entry(mediator_events, EventUnlockSuccess, {}) and must_contain_entry(mediator_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_mediator_events, network_wait) def test_target_events(): target_events = app2.raiden.wal.storage.get_events() return ( must_contain_entry(target_events, SendSecretRequest, {}) and must_contain_entry(target_events, SendSecretReveal, {}) and must_contain_entry(target_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_target_events, network_wait)
def run_test_mediated_transfer_events( raiden_network, number_of_nodes, token_addresses, network_wait, ): app0, app1, app2 = raiden_network token_address = token_addresses[0] amount = 10 transfer( initiator_app=app0, target_app=app2, token_address=token_address, amount=amount, identifier=1, timeout=network_wait * number_of_nodes, ) def test_initiator_events(): initiator_events = app0.raiden.wal.storage.get_events() return ( search_for_item(initiator_events, SendSecretReveal, {}) and search_for_item(initiator_events, EventUnlockSuccess, {}) ) assert wait_until(test_initiator_events, network_wait) def test_mediator_events(): mediator_events = app1.raiden.wal.storage.get_events() return ( search_for_item(mediator_events, EventUnlockSuccess, {}) and search_for_item(mediator_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_mediator_events, network_wait) def test_target_events(): target_events = app2.raiden.wal.storage.get_events() return ( search_for_item(target_events, SendSecretRequest, {}) and search_for_item(target_events, SendSecretReveal, {}) and search_for_item(target_events, EventUnlockClaimSuccess, {}) ) assert wait_until(test_target_events, network_wait)
def run_test_echo_node_response(token_addresses, raiden_chain, network_wait): app0, app1, app2, echo_app = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() expected = list() # Create some transfers for num, app in enumerate([app0, app1, app2]): amount = 1 + num payment_status = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** (num + 1), ) payment_status.payment_done.wait(timeout=20) expected.append(amount) while echo_node.num_handled_transfers < len(expected): gevent.sleep(.5) # Check that all transfers were handled correctly def test_events(handled_transfer): app = address_to_app[handled_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address, ) received = { event.identifier: event for event in events if type(event) == EventPaymentReceivedSuccess } if len(received) != 1: return None transfer = received.popitem()[1] is_not_valid = ( transfer.initiator != echo_app.raiden.address or transfer.identifier != handled_transfer.identifier + transfer.amount ) if is_not_valid: return None return transfer for handled_transfer in echo_node.seen_transfers: assert wait_until(lambda: test_events(handled_transfer), network_wait) echo_node.stop()
def test_echo_node_response(token_addresses, raiden_chain, network_wait): app0, app1, app2, echo_app = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() expected = list() # Create some transfers for num, app in enumerate([app0, app1, app2]): amount = 1 + num transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** (num + 1), ) transfer_event.wait(timeout=20) expected.append(amount) while echo_node.num_handled_transfers < len(expected): gevent.sleep(.5) # Check that all transfers were handled correctly def test_events(handled_transfer): app = address_to_app[handled_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address, ) received = { event.identifier: event for event in events if type(event) == EventPaymentReceivedSuccess } if len(received) != 1: return transfer = received.popitem()[1] is_not_valid = ( transfer.initiator != echo_app.raiden.address or transfer.identifier != handled_transfer.identifier + transfer.amount ) if is_not_valid: return return transfer for handled_transfer in echo_node.seen_transfers: assert wait_until(lambda: test_events(handled_transfer), network_wait) echo_node.stop()
def test_mediated_transfer_events(raiden_network, number_of_nodes, token_addresses, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] amount = 10 transfer( initiator_app=app0, target_app=app2, token_address=token_address, amount=PaymentAmount(amount), identifier=PaymentID(1), timeout=network_wait * number_of_nodes, ) def test_initiator_events(): assert not has_unlock_failure(app0.raiden) initiator_events = app0.raiden.wal.storage.get_events() secret_reveal = search_for_item(initiator_events, SendSecretReveal, {}) unlock_success = search_for_item(initiator_events, EventUnlockSuccess, {}) return secret_reveal and unlock_success assert wait_until(test_initiator_events, network_wait) def test_mediator_events(): assert not has_unlock_failure(app1.raiden) mediator_events = app1.raiden.wal.storage.get_events() unlock_success = search_for_item(mediator_events, EventUnlockSuccess, {}) unlock_claim_success = search_for_item(mediator_events, EventUnlockClaimSuccess, {}) return unlock_success and unlock_claim_success assert wait_until(test_mediator_events, network_wait) def test_target_events(): assert not has_unlock_failure(app2.raiden) target_events = app2.raiden.wal.storage.get_events() return (search_for_item(target_events, SendSecretRequest, {}) and search_for_item(target_events, SendSecretReveal, {}) and search_for_item(target_events, EventUnlockClaimSuccess, {})) assert wait_until(test_target_events, network_wait)
def test_echo_node_response(token_addresses, raiden_chain, network_wait): app0, app1, app2, echo_app = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() expected = list() # Create some transfers for num, app in enumerate([app0, app1, app2]): amount = 1 + num transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10**(num + 1), ) transfer_event.wait(timeout=20) expected.append(amount) while echo_node.num_handled_transfers < len(expected): gevent.sleep(.5) # Check that all transfers were handled correctly def test_events(handled_transfer): app = address_to_app[handled_transfer['initiator']] events = get_channel_events_for_token( app, app.raiden.default_registry.address, token_address, 0, ) received = { event['identifier']: event for event in events if event['event'] == 'EventTransferReceivedSuccess' } if len(received) != 1: return transfer = received.popitem()[1] if (transfer['initiator'] != echo_app.raiden.address or transfer['identifier'] != handled_transfer['identifier'] + transfer['amount']): return return transfer for handled_transfer in echo_node.seen_transfers: assert wait_until(lambda: test_events(handled_transfer), network_wait) echo_node.stop()
def deposit(self, token_address, partner_address, amount): """ Deposit `amount` in the channel with the peer at `partner_address` and the given `token_address` in order to be able to do transfers. """ if not isaddress(token_address): raise InvalidAddress( 'Expected binary address format for token in channel deposit') if not isaddress(partner_address): raise InvalidAddress( 'Expected binary address format for partner in channel deposit' ) graph = self.raiden.token_to_channelgraph[token_address] channel = graph.partneraddress_to_channel[partner_address] netcontract_address = channel.external_state.netting_channel.address assert len(netcontract_address) # Obtain a reference to the token and approve the amount for funding token = self.raiden.chain.token(token_address) balance = token.balance_of(self.raiden.address.encode('hex')) if not balance >= amount: msg = "Not enough balance for token'{}' [{}]: have={}, need={}".format( token.proxy.name(), pex(token_address), balance, amount) raise InsufficientFunds(msg) token.approve(netcontract_address, amount) # Obtain the netting channel and fund it by depositing the amount old_balance = channel.contract_balance netting_channel = self.raiden.chain.netting_channel( netcontract_address) # actually make the deposit, and wait for it to be mined netting_channel.deposit(amount) # Wait until the balance has been updated via a state transition triggered # by processing the `ChannelNewBalance` event. # Usually, it'll take a single gevent.sleep, as we already have waited # for it to be mined, and only need to give the event handling greenlet # the chance to process the event, but let's wait 10s to be safe wait_timeout_secs = 10 # FIXME: hardcoded timeout if not wait_until( lambda: channel.contract_balance != old_balance, wait_timeout_secs, self.raiden.alarm.wait_time, ): raise EthNodeCommunicationError( 'After {} seconds the deposit was not properly processed.'. format(wait_timeout_secs)) return channel
def test_event_transfer_received_success( token_addresses, raiden_chain, network_wait, skip_if_not_udp, ): app0, app1, app2, receiver_app = raiden_chain token_address = token_addresses[0] expected = dict() for num, app in enumerate([app0, app1, app2]): amount = 1 + num transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, receiver_app.raiden.address, ) transfer_event.wait(timeout=20) expected[app.raiden.address] = amount # sleep is for the receiver's node to have time to process all events gevent.sleep(1) def test_events(amount, address): events = receiver_app.raiden.wal.storage.get_events_by_block( 0, 'latest') events = [e[1] for e in events] return must_contain_entry( events, EventTransferReceivedSuccess, { 'amount': amount, 'initiator': address }, ) amounts = [1, 2, 3] addrs = [app0.raiden.address, app1.raiden.address, app2.raiden.address] for amount, address in zip(amounts, addrs): assert wait_until( lambda: test_events(amount, address), network_wait, )
def test_event_transfer_received_success( token_addresses, raiden_chain, network_wait, ): app0, app1, app2, receiver_app = raiden_chain token_address = token_addresses[0] expected = dict() for num, app in enumerate([app0, app1, app2]): amount = 1 + num transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, receiver_app.raiden.address, ) transfer_event.wait(timeout=20) expected[app.raiden.address] = amount # sleep is for the receiver's node to have time to process all events gevent.sleep(1) def test_events(amount, address): return search_for_item( receiver_app.raiden.wal.storage.get_events(), EventPaymentReceivedSuccess, { 'amount': amount, 'initiator': address }, ) amounts = [1, 2, 3] addrs = [app0.raiden.address, app1.raiden.address, app2.raiden.address] for amount, address in zip(amounts, addrs): assert wait_until( lambda: test_events(amount, address), network_wait, )
def test_event_transfer_received_success( token_addresses, raiden_chain, network_wait, ): app0, app1, app2, receiver_app = raiden_chain token_address = token_addresses[0] expected = dict() for num, app in enumerate([app0, app1, app2]): amount = 1 + num transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, receiver_app.raiden.address, ) transfer_event.wait(timeout=20) expected[app.raiden.address] = amount # sleep is for the receiver's node to have time to process all events gevent.sleep(1) def test_events(amount, address): return must_contain_entry( receiver_app.raiden.wal.storage.get_events(), EventPaymentReceivedSuccess, {'amount': amount, 'initiator': address}, ) amounts = [1, 2, 3] addrs = [app0.raiden.address, app1.raiden.address, app2.raiden.address] for amount, address in zip(amounts, addrs): assert wait_until( lambda: test_events(amount, address), network_wait, )
def deposit(self, token_address, partner_address, amount, poll_timeout=DEFAULT_POLL_TIMEOUT): """ Deposit `amount` in the channel with the peer at `partner_address` and the given `token_address` in order to be able to do transfers. Raises: InvalidAddress: If either token_address or partner_address is not 20 bytes long. TransactionThrew: May happen for multiple reasons: - If the token approval fails, e.g. the token may validate if account has enough balance for the allowance. - The deposit failed, e.g. the allowance did not set the token aside for use and the user spent it before deposit was called. - The channel was closed/settled between the allowance call and the deposit call. AddressWithoutCode: The channel was settled during the deposit execution. """ if not isaddress(token_address): raise InvalidAddress( 'Expected binary address format for token in channel deposit') if not isaddress(partner_address): raise InvalidAddress( 'Expected binary address format for partner in channel deposit' ) graph = self.raiden.token_to_channelgraph.get(token_address) if graph is None: raise InvalidAddress('Unknown token address') channel = graph.partneraddress_to_channel.get(partner_address) if channel is None: raise InvalidAddress( 'No channel with partner_address for the given token') if channel.token_address != token_address: raise InvalidAddress( 'token_address does not match the netting channel attribute') token = self.raiden.chain.token(token_address) netcontract_address = channel.external_state.netting_channel.address old_balance = channel.contract_balance # Checking the balance is not helpful since this requires multiple # transactions that can race, e.g. the deposit check succeed but the # user spent his balance before deposit. balance = token.balance_of(hexlify(self.raiden.address)) if not balance >= amount: msg = 'Not enough balance to deposit. {} Available={} Tried={}'.format( pex(token_address), balance, amount, ) raise InsufficientFunds(msg) token.approve(netcontract_address, amount) channel_proxy = self.raiden.chain.netting_channel(netcontract_address) channel_proxy.deposit(amount) # Wait until the `ChannelNewBalance` event is processed. # # Usually a single sleep is sufficient, since the `deposit` waits for # the transaction to be polled. sucess = wait_until( lambda: channel.contract_balance != old_balance, poll_timeout, self.raiden.alarm.wait_time, ) if not sucess: raise EthNodeCommunicationError( 'After {} seconds the deposit was not properly processed.'. format(poll_timeout)) return channel
def deposit(self, token_address, partner_address, amount, poll_timeout=DEFAULT_POLL_TIMEOUT): """ Deposit `amount` in the channel with the peer at `partner_address` and the given `token_address` in order to be able to do transfers. Raises: InvalidAddress: If either token_address or partner_address is not 20 bytes long. TransactionThrew: May happen for multiple reasons: - If the token approval fails, e.g. the token may validate if account has enough balance for the allowance. - The deposit failed, e.g. the allowance did not set the token aside for use and the user spent it before deposit was called. - The channel was closed/settled between the allowance call and the deposit call. AddressWithoutCode: The channel was settled during the deposit execution. """ if not isaddress(token_address): raise InvalidAddress('Expected binary address format for token in channel deposit') if not isaddress(partner_address): raise InvalidAddress('Expected binary address format for partner in channel deposit') graph = self.raiden.token_to_channelgraph.get(token_address) if graph is None: raise InvalidAddress('Unknown token address') channel = graph.partneraddress_to_channel.get(partner_address) if channel is None: raise InvalidAddress('No channel with partner_address for the given token') if channel.token_address != token_address: raise InvalidAddress('token_address does not match the netting channel attribute') token = self.raiden.chain.token(token_address) netcontract_address = channel.external_state.netting_channel.address old_balance = channel.contract_balance # Checking the balance is not helpful since this requires multiple # transactions that can race, e.g. the deposit check succeed but the # user spent his balance before deposit. balance = token.balance_of(hexlify(self.raiden.address)) if not balance >= amount: msg = 'Not enough balance to deposit. {} Available={} Tried={}'.format( pex(token_address), balance, amount, ) raise InsufficientFunds(msg) token.approve(netcontract_address, amount) channel_proxy = self.raiden.chain.netting_channel(netcontract_address) channel_proxy.deposit(amount) # Wait until the `ChannelNewBalance` event is processed. # # Usually a single sleep is sufficient, since the `deposit` waits for # the transaction to be polled. sucess = wait_until( lambda: channel.contract_balance != old_balance, poll_timeout, self.raiden.alarm.wait_time, ) if not sucess: raise EthNodeCommunicationError( 'After {} seconds the deposit was not properly processed.'.format( poll_timeout ) ) return channel
def run_test_clear_closed_queue(raiden_network, token_addresses, network_wait): app0, app1 = raiden_network hold_event_handler = app1.raiden.raiden_event_handler registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] chain_state0 = views.state_from_app(app0) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state0, app0.raiden.default_registry.address, token_address) token_network = views.get_token_network_by_identifier( chain_state0, token_network_identifier) channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier assert (channel_identifier in token_network.partneraddresses_to_channelidentifiers[ app1.raiden.address]) target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) # make an unconfirmed transfer to ensure the nodes have communicated amount = 10 payment_identifier = 1337 app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=0, target=target, identifier=payment_identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=secret, ) app1.raiden.transport.stop() app1.raiden.transport.get() # make sure to wait until the queue is created def has_initiator_events(): initiator_events = app0.raiden.wal.storage.get_events() return search_for_item(initiator_events, SendLockedTransfer, {}) assert wait_until(has_initiator_events, network_wait) # assert the specific queue is present chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert [(queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue_id.channel_identifier == channel_identifier and queue] # A ChannelClose event will be generated, this will be polled by both apps RaidenAPI(app0.raiden).channel_close(registry_address, token_address, app1.raiden.address) exception = ValueError("Could not get close event") with gevent.Timeout(seconds=30, exception=exception): waiting.wait_for_close( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.sleep_time, ) # assert all queues with this partner are gone or empty chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert not [(queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue] chain_state1 = views.state_from_app(app1) queues1 = views.get_all_messagequeues(chain_state=chain_state1) assert not [(queue_id, queue) for queue_id, queue in queues1.items() if queue_id.recipient == app0.raiden.address and queue]
def run_test_echo_node_lottery(token_addresses, raiden_chain, network_wait): app0, app1, app2, app3, echo_app, app4, app5, app6 = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() expected = list() # Let 6 participants enter the pool amount = 7 for num, app in enumerate([app0, app1, app2, app3, app4, app5]): payment_status = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** (num + 1), ) payment_status.payment_done.wait(timeout=20) expected.append(amount) # test duplicated identifier + amount is ignored payment_status = RaidenAPI(app5.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, # same amount as before echo_app.raiden.address, 10 ** 6, # app5 used this identifier before ).payment_done.wait(timeout=20) # test pool size querying pool_query_identifier = 77 # unused identifier different from previous one payment_status = RaidenAPI(app5.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, pool_query_identifier, ).payment_done.wait(timeout=20) expected.append(amount) # fill the pool payment_status = RaidenAPI(app6.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** 7, ).payment_done.wait(timeout=20) expected.append(amount) while echo_node.num_handled_transfers < len(expected): gevent.sleep(.5) def get_echoed_transfer(sent_transfer): """For a given transfer sent to echo node, get the corresponding echoed transfer""" app = address_to_app[sent_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address, ) def is_valid(event): return ( type(event) == EventPaymentReceivedSuccess and event.initiator == echo_app.raiden.address and event.identifier == sent_transfer.identifier + event.amount ) received = { event.identifier: event for event in events if is_valid(event) } if len(received) != 1: return None return received.popitem()[1] def received_is_of_size(size): """Return transfers received from echo_node when there's size transfers""" received = {} # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: event = get_echoed_transfer(handled_transfer) if not event: continue received[event.identifier] = event if len(received) == size: return received return None # wait for the expected echoed transfers to be handled received = wait_until(lambda: received_is_of_size(2), 2 * network_wait) assert received received = sorted(received.values(), key=lambda transfer: transfer.amount) pool_query = received[0] assert pool_query.amount == 6 assert pool_query.identifier == pool_query_identifier + 6 winning_transfer = received[1] assert winning_transfer.initiator == echo_app.raiden.address assert winning_transfer.amount == 49 assert (winning_transfer.identifier - 49) % 10 == 0 echo_node.stop()
def test_echo_node_lottery(token_addresses, raiden_chain, network_wait): app0, app1, app2, app3, echo_app, app4, app5, app6 = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() transfer_timeout = 10 # Let 6 participants enter the pool amount = 7 for num, app in enumerate([app0, app1, app2, app3, app4, app5]): identifier = 100 * num with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=identifier, timeout=transfer_timeout, ) # test duplicated identifier + amount is ignored with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app5, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=500, # app5 used this identifier before timeout=transfer_timeout, ) # test pool size querying pool_query_identifier = 77 # unused identifier different from previous one with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app5, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=pool_query_identifier, timeout=transfer_timeout, ) # fill the pool with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app6, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=600, timeout=transfer_timeout, ) def get_echoed_transfer( sent_transfer) -> Optional[EventPaymentReceivedSuccess]: """For a given transfer sent to echo node, get the corresponding echoed transfer""" app = address_to_app[sent_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address) for event in events: if not type(event) == EventPaymentReceivedSuccess: continue assert isinstance(event, EventPaymentReceivedSuccess), MYPY_ANNOTATION if not (event.initiator == echo_app.raiden.address and event.identifier == sent_transfer.identifier + event.amount): continue return event return None def received_events_when_len( size: int) -> Optional[List[EventPaymentReceivedSuccess]]: """Return transfers received from echo_node when there's size transfers""" received_events = [] # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: event = get_echoed_transfer(handled_transfer) if not event: continue received_events.append(event) log.debug( "Checking number of received events", received_events=received_events, expected_size=size, actual_size=len(received_events), seen_transfers=echo_node.seen_transfers, received_transfers=received_events, ) if len(received_events) == size: return received_events return None # wait for the expected echoed transfers to be handled received = wait_until(func=lambda: received_events_when_len(2), wait_for=network_wait) assert received received.sort(key=lambda transfer: transfer.amount) pool_query = received[0] assert pool_query.amount == 6 assert pool_query.identifier == pool_query_identifier + 6 winning_transfer = received[1] assert winning_transfer.initiator == echo_app.raiden.address assert winning_transfer.amount == 49 assert (winning_transfer.identifier - 49) % 10 == 0 echo_node.stop()
def test_clear_closed_queue(raiden_network, token_addresses, deposit, network_wait): """ Closing a channel clears the respective message queue. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] chain_state0 = views.state_from_app(app0) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state0, app0.raiden.default_registry.address, token_address, ) token_network = views.get_token_network_by_identifier( chain_state0, token_network_identifier, ) channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[ app1.raiden.address] with dont_handle_secret_request_mock(app0): # make an unconfirmed transfer to ensure the nodes have communicated amount = 10 payment_identifier = 1337 app0.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=app1.raiden.address, identifier=payment_identifier, ) app1.raiden.transport.stop() app1.raiden.transport.get() # make sure to wait until the queue is created def has_initiator_events(): initiator_events = app0.raiden.wal.storage.get_events() return must_contain_entry(initiator_events, SendLockedTransfer, {}) assert wait_until(has_initiator_events, network_wait) # assert the specific queue is present chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert [(queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue_id.channel_identifier == channel_identifier and queue] # A ChannelClose event will be generated, this will be polled by both apps RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) exception = ValueError('Could not get close event') with gevent.Timeout(seconds=30, exception=exception): waiting.wait_for_close( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.sleep_time, ) # assert all queues with this partner are gone or empty chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert not [(queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue] chain_state1 = views.state_from_app(app1) queues1 = views.get_all_messagequeues(chain_state=chain_state1) assert not [(queue_id, queue) for queue_id, queue in queues1.items() if queue_id.recipient == app0.raiden.address and queue]
def test_clear_closed_queue(raiden_network, token_addresses, deposit, network_wait): """ Closing a channel clears the respective message queue. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] chain_state0 = views.state_from_app(app0) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state0, app0.raiden.default_registry.address, token_address, ) token_network = views.get_token_network_by_identifier( chain_state0, token_network_identifier, ) channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[ app1.raiden.address ] with dont_handle_secret_request_mock(app0): # make an unconfirmed transfer to ensure the nodes have communicated amount = 10 payment_identifier = 1337 app0.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=app1.raiden.address, identifier=payment_identifier, ) app1.raiden.transport.stop() app1.raiden.transport.get() # make sure to wait until the queue is created def has_initiator_events(): initiator_events = app0.raiden.wal.storage.get_events() return must_contain_entry(initiator_events, SendLockedTransfer, {}) assert wait_until(has_initiator_events, network_wait) # assert the specific queue is present chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert [ (queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue_id.channel_identifier == channel_identifier and queue ] # A ChannelClose event will be generated, this will be polled by both apps RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) exception = ValueError('Could not get close event') with gevent.Timeout(seconds=30, exception=exception): waiting.wait_for_close( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.sleep_time, ) # assert all queues with this partner are gone or empty chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert not [ (queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue ] chain_state1 = views.state_from_app(app1) queues1 = views.get_all_messagequeues(chain_state=chain_state1) assert not [ (queue_id, queue) for queue_id, queue in queues1.items() if queue_id.recipient == app0.raiden.address and queue ]
def test_clear_closed_queue(raiden_network: List[App], token_addresses, network_wait): """ Closing a channel clears the respective message queue. """ app0, app1 = raiden_network hold_event_handler = app1.raiden.raiden_event_handler assert isinstance(hold_event_handler, HoldRaidenEventHandler) registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] chain_state0 = views.state_from_app(app0) token_network_address = views.get_token_network_address_by_token_address( chain_state0, app0.raiden.default_registry.address, token_address) assert token_network_address token_network = views.get_token_network_by_address(chain_state0, token_network_address) assert token_network channel_identifier = get_channelstate(app0, app1, token_network_address).identifier assert (channel_identifier in token_network.partneraddresses_to_channelidentifiers[ app1.raiden.address]) target = app1.raiden.address secret = Secret(sha3(target)) secrethash = sha256_secrethash(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) # make an unconfirmed transfer to ensure the nodes have communicated amount = PaymentAmount(10) payment_identifier = PaymentID(1337) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=TargetAddress(target), identifier=payment_identifier, secret=secret, ) app1.raiden.transport.stop() app1.raiden.transport.greenlet.get() # make sure to wait until the queue is created def has_initiator_events(): assert app0.raiden.wal, "raiden server must have been started" initiator_events = app0.raiden.wal.storage.get_events() return search_for_item(initiator_events, SendLockedTransfer, {}) assert wait_until(has_initiator_events, network_wait) # assert the specific queue is present chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert [ (queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue_id. canonical_identifier.channel_identifier == channel_identifier and queue ] # A ChannelClose event will be generated, this will be polled by both apps RaidenAPI(app0.raiden).channel_close(registry_address, token_address, app1.raiden.address) exception = ValueError("Could not get close event") with gevent.Timeout(seconds=30, exception=exception): waiting.wait_for_close( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.sleep_time, ) # assert all queues with this partner are gone or empty chain_state0 = views.state_from_app(app0) queues0 = views.get_all_messagequeues(chain_state=chain_state0) assert not [(queue_id, queue) for queue_id, queue in queues0.items() if queue_id.recipient == app1.raiden.address and queue] chain_state1 = views.state_from_app(app1) queues1 = views.get_all_messagequeues(chain_state=chain_state1) assert not [(queue_id, queue) for queue_id, queue in queues1.items() if queue_id.recipient == app0.raiden.address and queue]
def test_echo_node_lottery(token_addresses, raiden_chain, network_wait): app0, app1, app2, app3, echo_app, app4, app5, app6 = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() expected = list() # Let 6 participants enter the pool amount = 7 for num, app in enumerate([app0, app1, app2, app3, app4, app5]): transfer_event = RaidenAPI(app.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** (num + 1), ) transfer_event.wait(timeout=20) expected.append(amount) # test duplicated identifier + amount is ignored transfer_event = RaidenAPI(app5.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, # same amount as before echo_app.raiden.address, 10 ** 6, # app5 used this identifier before ).wait(timeout=20) # test pool size querying pool_query_identifier = 77 # unused identifier different from previous one transfer_event = RaidenAPI(app5.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, pool_query_identifier, ).wait(timeout=20) expected.append(amount) # fill the pool transfer_event = RaidenAPI(app6.raiden).transfer_async( app.raiden.default_registry.address, token_address, amount, echo_app.raiden.address, 10 ** 7, ).wait(timeout=20) expected.append(amount) while echo_node.num_handled_transfers < len(expected): gevent.sleep(.5) def get_echoed_transfer(sent_transfer): """For a given transfer sent to echo node, get the corresponding echoed transfer""" app = address_to_app[sent_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address, ) def is_valid(event): return ( type(event) == EventPaymentReceivedSuccess and event.initiator == echo_app.raiden.address and event.identifier == sent_transfer.identifier + event.amount ) received = { event.identifier: event for event in events if is_valid(event) } if len(received) != 1: return return received.popitem()[1] def received_is_of_size(size): """Return transfers received from echo_node when there's size transfers""" received = {} # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: event = get_echoed_transfer(handled_transfer) if not event: continue received[event.identifier] = event if len(received) == size: return received # wait for the expected echoed transfers to be handled received = wait_until(lambda: received_is_of_size(2), 2 * network_wait) assert received received = sorted(received.values(), key=lambda transfer: transfer.amount) pool_query = received[0] assert pool_query.amount == 6 assert pool_query.identifier == pool_query_identifier + 6 winning_transfer = received[1] assert winning_transfer.initiator == echo_app.raiden.address assert winning_transfer.amount == 49 assert (winning_transfer.identifier - 49) % 10 == 0 echo_node.stop()