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_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 test_echo_node_response(token_addresses, raiden_chain): 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 for handled_transfer in echo_node.seen_transfers: app = address_to_app[handled_transfer['initiator']] events = get_channel_events_for_token( app.raiden.default_registry.address, app, token_address, 0, ) received = {} for event in events: if event['event'] == 'EventTransferReceivedSuccess': received[repr(event)] = event assert len(received) == 1 transfer = list(received.values())[0] assert transfer['initiator'] == echo_app.raiden.address assert transfer['identifier'] == (handled_transfer['identifier'] + transfer['amount']) echo_node.stop()
class EchoNodeRunner(NodeRunner): def __init__(self, options: Dict[str, Any], ctx, token_address: typing.TokenAddress): super().__init__(options, ctx) self._token_address = token_address self._echo_node = None @property def welcome_string(self): return '{} [ECHO NODE]'.format(super().welcome_string) def _startup_hook(self): self._echo_node = EchoNode(self._raiden_api, self._token_address) def _shutdown_hook(self): self._echo_node.stop()
def test_echo_node_response(token_addresses, raiden_chain): 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( 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 for handled_transfer in echo_node.seen_transfers: app = address_to_app[handled_transfer['initiator']] events = get_channel_events_for_token(app, token_address, 0) received = {} for event in events: if event['_event_type'] == 'EventTransferReceivedSuccess': received[repr(event)] = event assert len(received) == 1 transfer = list(received.values())[0] assert transfer['initiator'] == echo_app.raiden.address assert transfer['identifier'] == ( handled_transfer['identifier'] + transfer['amount'] ) echo_node.stop()
class EchoNodeRunner(NodeRunner): def __init__(self, options: Dict[str, Any], ctx: Context, token_address: TokenAddress) -> None: super().__init__(options, ctx) self._token_address = token_address self._echo_node: Optional[EchoNode] = None def run(self) -> None: super().run() self._start_services() @property def welcome_string(self) -> str: return "{} [ECHO NODE]".format(super().welcome_string) def _startup_hook(self) -> None: if self.raiden_api is not None: self._echo_node = EchoNode(self.raiden_api, self._token_address) def _shutdown_hook(self) -> None: if self._echo_node: self._echo_node.stop()
def test_echo_node_response(token_addresses, raiden_chain, retry_timeout): app0, app1, echo_app = raiden_chain token_address = token_addresses[0] registry_address = echo_app.raiden.default_registry.address echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) message_handler = WaitForMessage() echo_app.raiden.message_handler = message_handler echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() transfer_timeout = 10 wait_for = list() for num, app in enumerate([app0, app1]): amount = PaymentAmount(1 + num) identifier = PaymentID(10 ** (num + 1)) secret, secrethash = make_secret_with_hash() payment_status = RaidenAPI(app.raiden).transfer_async( registry_address=registry_address, token_address=token_address, amount=amount, target=echo_app.raiden.address, identifier=identifier, secret=secret, secrethash=secrethash, ) wait = message_handler.wait_for_message(Unlock, {"secret": secret}) wait_for.append((wait, app.raiden.address, amount, identifier)) msg = ( f"Transfer {identifier} from " f"{to_checksum_address(app.raiden.address)} to " f"{to_checksum_address(echo_app.raiden.address)} timed out after " f"{transfer_timeout}" ) timeout = gevent.Timeout(transfer_timeout, exception=RuntimeError(msg)) with watch_for_unlock_failures(*raiden_chain), timeout: payment_status.payment_done.wait() echo_identifier = PaymentID(identifier + amount) msg = ( f"Response transfer {echo_identifier} from echo node " f"{to_checksum_address(echo_app.raiden.address)} to " f"{to_checksum_address(app.raiden.address)} timed out after " f"{transfer_timeout}" ) with gevent.Timeout(transfer_timeout, exception=RuntimeError(msg)): result = wait_for_received_transfer_result( raiden=app.raiden, payment_identifier=echo_identifier, amount=amount, retry_timeout=retry_timeout, secrethash=secrethash, ) assert result == TransferWaitResult.UNLOCKED for wait, sender, amount, ident in wait_for: wait.wait() assert search_for_item( echo_app.raiden.wal.storage.get_events(), EventPaymentReceivedSuccess, { "amount": amount, "identifier": ident, "initiator": sender, "token_network_registry_address": registry_address, }, ) 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_echo_node_lottery(token_addresses, raiden_chain): 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( 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( 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( 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( 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) received = {} # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: app = address_to_app[handled_transfer['initiator']] events = get_channel_events_for_token(app, token_address, 0) for event in events: if event['_event_type'] == 'EventTransferReceivedSuccess': received[repr(event)] = event assert len(received) == 2 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 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() 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()
def test_echo_node_lottery(token_addresses, raiden_chain): 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( 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( 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( 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( 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) received = {} # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: app = address_to_app[handled_transfer['initiator']] events = get_channel_events_for_token(app, token_address, 0) for event in events: if event['_event_type'] == 'EventTransferReceivedSuccess': received[repr(event)] = event assert len(received) == 2 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()