diff --git a/src/node/waku_node.py b/src/node/waku_node.py index 1d9d073cee..fac55965bd 100644 --- a/src/node/waku_node.py +++ b/src/node/waku_node.py @@ -2,6 +2,7 @@ import errno import json import os import shutil +import subprocess import pytest import requests @@ -35,12 +36,14 @@ def sanitize_docker_flags(input_flags): @retry(stop=stop_after_delay(180), wait=wait_fixed(0.5), reraise=True) -def rln_credential_store_ready(creds_file_path): +def rln_credential_store_ready(creds_file_path, single_check=False): if os.path.exists(creds_file_path): return True - else: + elif not single_check: raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), creds_file_path) + return False + def peer_info2multiaddr(peer, is_nwaku=True): if is_nwaku: @@ -147,8 +150,9 @@ class WakuNode: rln_args, rln_creds_set, keystore_path = self.parse_rln_credentials(default_args, False) - del default_args["rln-creds-id"] - del default_args["rln-creds-source"] + default_args.pop("rln-creds-id", None) + default_args.pop("rln-creds-source", None) + default_args.pop("rln-keystore-prefix", None) if rln_creds_set: rln_credential_store_ready(keystore_path) @@ -187,10 +191,7 @@ class WakuNode: self._api = REST(self._rest_port) self._volumes = [] - default_args = { - "rln-creds-id": None, - "rln-creds-source": None, - } + default_args = {"rln-creds-id": None, "rln-creds-source": None, "rln-relay-user-message-limit-registration": 100} default_args.update(sanitize_docker_flags(kwargs)) @@ -436,7 +437,7 @@ class WakuNode: eth_private_key = select_private_key(imported_creds, selected_id) - current_working_directory = os.getcwd() + cwd = os.getcwd() if self.is_nwaku(): if is_registration: @@ -444,6 +445,7 @@ class WakuNode: { "generateRlnKeystore": None, "--execute": None, + "rln-relay-user-message-limit": default_args["rln-relay-user-message-limit-registration"], } ) else: @@ -453,22 +455,30 @@ class WakuNode: } ) - rln_args.update( - { - "rln-relay-cred-path": "/keystore/keystore.json", - "rln-relay-cred-password": imported_creds["rln-relay-cred-password"], - "rln-relay-eth-client-address": imported_creds["rln-relay-eth-client-address"], - "rln-relay-eth-contract-address": imported_creds["rln-relay-eth-contract-address"], - "rln-relay-eth-private-key": imported_creds[eth_private_key], - } - ) + if not default_args.get("rln-relay-dynamic") and not is_registration: + rln_args.update( + { + "rln-relay-cred-path": "/keystore/keystore.json", + "rln-relay-cred-password": imported_creds["rln-relay-cred-password"], + } + ) + else: + rln_args.update( + { + "rln-relay-cred-path": "/keystore/keystore.json", + "rln-relay-cred-password": imported_creds["rln-relay-cred-password"], + "rln-relay-eth-client-address": imported_creds["rln-relay-eth-client-address"], + "rln-relay-eth-contract-address": imported_creds["rln-relay-eth-contract-address"], + "rln-relay-eth-private-key": imported_creds[eth_private_key], + } + ) - keystore_path = current_working_directory + "/keystore_" + selected_id + "/keystore.json" + keystore_path = cwd + "/keystore_" + default_args["rln-keystore-prefix"] + "_" + selected_id + "/keystore.json" self._volumes.extend( [ - current_working_directory + "/rln_tree_" + selected_id + ":/etc/rln_tree", - current_working_directory + "/keystore_" + selected_id + ":/keystore", + cwd + "/rln_tree_" + default_args["rln-keystore-prefix"] + "_" + selected_id + ":/etc/rln_tree", + cwd + "/keystore_" + default_args["rln-keystore-prefix"] + "_" + selected_id + ":/keystore", ] ) diff --git a/src/steps/rln.py b/src/steps/rln.py index e7c5289286..2300804010 100644 --- a/src/steps/rln.py +++ b/src/steps/rln.py @@ -1,5 +1,8 @@ import os import inspect +import random +import string + import pytest import allure @@ -22,19 +25,26 @@ class StepsRLN(StepsCommon): optional_nodes = [] multiaddr_list = [] lightpush_nodes = [] + keystore_prefixes = [] - @pytest.fixture(scope="function") - def register_main_rln_relay_nodes(self, request): - logger.debug(f"Running fixture setup: {inspect.currentframe().f_code.co_name}") - self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="1") - self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="2") + @allure.step + def generate_keystore_prefixes(self, count=2): + new_prefixes = [] + for _ in range(count): + new_prefixes.append("".join(random.choices(string.ascii_lowercase, k=4))) - @pytest.fixture(scope="function") - def register_optional_rln_relay_nodes(self, request): - logger.debug(f"Running fixture setup: {inspect.currentframe().f_code.co_name}") - self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="3") - self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="4") - self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="5") + return new_prefixes + + @allure.step + def register_rln_relay_nodes(self, count, orig_prefixes): + if count > 0: + self.keystore_prefixes = self.generate_keystore_prefixes(count) + for i, prefix in enumerate(self.keystore_prefixes): + self.register_rln_single_node(prefix=prefix, rln_creds_source=RLN_CREDENTIALS, rln_creds_id=f"{i+1}") + else: + self.keystore_prefixes = orig_prefixes + + return self.keystore_prefixes @allure.step def setup_main_rln_relay_nodes(self, **kwargs): @@ -50,6 +60,7 @@ class StepsRLN(StepsCommon): rln_creds_source=RLN_CREDENTIALS, rln_creds_id="1", rln_relay_membership_index="1", + rln_keystore_prefix=self.keystore_prefixes[0], **kwargs, ) self.enr_uri = self.node1.get_enr_uri() @@ -67,6 +78,7 @@ class StepsRLN(StepsCommon): rln_creds_source=RLN_CREDENTIALS, rln_creds_id="2", rln_relay_membership_index="1", + rln_keystore_prefix=self.keystore_prefixes[1], **kwargs, ) self.add_node_peer(self.node2, [self.multiaddr_with_id]) @@ -89,30 +101,41 @@ class StepsRLN(StepsCommon): rln_creds_source=RLN_CREDENTIALS, rln_creds_id=f"{index + 3}", rln_relay_membership_index="1", + rln_keystore_prefix=self.keystore_prefixes[index + 2], **kwargs, ) self.add_node_peer(node, [self.multiaddr_with_id]) self.optional_nodes.append(node) @allure.step - def setup_second_lightpush_node(self, relay="false", **kwargs): + def setup_second_rln_lightpush_node(self, relay="true", **kwargs): self.light_push_node2 = WakuNode(NODE_2, f"lightpush_node2_{self.test_id}") - self.light_push_node2.start(relay=relay, discv5_bootstrap_node=self.enr_uri, lightpush="true", lightpushnode=self.multiaddr_list[0], **kwargs) + self.light_push_node2.start( + relay=relay, + discv5_bootstrap_node=self.enr_uri, + lightpush="true", + lightpushnode=self.multiaddr_list[0], + rln_creds_source=RLN_CREDENTIALS, + rln_creds_id="2", + rln_relay_membership_index="1", + rln_keystore_prefix=self.keystore_prefixes[1], + **kwargs, + ) if relay == "true": self.main_nodes.extend([self.light_push_node2]) self.lightpush_nodes.extend([self.light_push_node2]) self.add_node_peer(self.light_push_node2, self.multiaddr_list) @allure.step - def register_rln_single_node(self, **kwargs): + def register_rln_single_node(self, prefix="", **kwargs): logger.debug("Registering RLN credentials for single node") - self.node1 = WakuNode(DEFAULT_NWAKU, f"node1_{gen_step_id()}") - self.node1.register_rln(rln_creds_source=kwargs["rln_creds_source"], rln_creds_id=kwargs["rln_creds_id"]) + self.node = WakuNode(DEFAULT_NWAKU, f"node_{gen_step_id()}") + self.node.register_rln(rln_keystore_prefix=prefix, rln_creds_source=kwargs["rln_creds_source"], rln_creds_id=kwargs["rln_creds_id"]) @allure.step - def check_rln_registration(self, key_id): - current_working_directory = os.getcwd() - creds_file_path = f"{current_working_directory}/keystore_{key_id}/keystore.json" + def check_rln_registration(self, prefix, key_id): + cwd = os.getcwd() + creds_file_path = f"{cwd}/keystore_{prefix}_{key_id}/keystore.json" try: rln_credential_store_ready(creds_file_path) except Exception as ex: diff --git a/tests/relay/test_rln.py b/tests/relay/test_rln.py index f603c188bb..4707635c18 100644 --- a/tests/relay/test_rln.py +++ b/tests/relay/test_rln.py @@ -14,45 +14,72 @@ logger = get_custom_logger(__name__) @pytest.mark.xdist_group(name="RLN serial tests") -@pytest.mark.usefixtures("register_main_rln_relay_nodes") @pytest.mark.skipif("go-waku" in (NODE_1 + NODE_2), reason="Test works only with nwaku") -@pytest.mark.skip(reason="waiting to resolve registration https://github.com/waku-org/nwaku/issues/2837") class TestRelayRLN(StepsRLN, StepsRelay): - def test_valid_payloads_at_slow_rate(self): - self.setup_main_rln_relay_nodes() + SAMPLE_INPUTS_RLN = SAMPLE_INPUTS + SAMPLE_INPUTS + SAMPLE_INPUTS + + def test_valid_payloads_lightpush_at_spam_rate(self, pytestconfig): + message_limit = 1 + epoch_sec = 1 + pytestconfig.cache.set("keystore-prefixes", self.register_rln_relay_nodes(2, [])) + self.setup_first_rln_relay_node(lightpush="true", rln_relay_user_message_limit=message_limit, rln_relay_epoch_sec=epoch_sec) + self.setup_second_rln_lightpush_node(rln_relay_user_message_limit=message_limit, rln_relay_epoch_sec=epoch_sec) self.subscribe_main_relay_nodes() - failed_payloads = [] - for payload in SAMPLE_INPUTS: + start = math.trunc(time()) + for i, payload in enumerate(SAMPLE_INPUTS[:5]): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: + logger.debug(f"Sending message No. #{i + 1}") + now = math.trunc(time()) + self.publish_message(message=message, sender=self.light_push_node2, use_lightpush=True) + if i > message_limit and (now - start) <= epoch_sec: + raise AssertionError("Publish with RLN enabled at spam rate worked!!!") + except Exception as e: + assert "RLN validation failed" or "NonceLimitReached" in str(e) + + def test_valid_payloads_at_slow_rate(self, pytestconfig): + message_limit = 20 + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=message_limit, rln_relay_epoch_sec=600) + self.subscribe_main_relay_nodes() + failed_payloads = [] + for i, payload in enumerate(self.SAMPLE_INPUTS_RLN): + logger.debug(f'Running test with payload {payload["description"]}') + message = self.create_message(payload=to_base64(payload["value"])) + try: + logger.debug(f"Sending message No. #{i + 1}") self.check_published_message_reaches_relay_peer(message, message_propagation_delay=0.2) except Exception as e: logger.error(f'Payload {payload["description"]} failed: {str(e)}') failed_payloads.append(payload["description"]) delay(1) assert not failed_payloads, f"Payloads failed: {failed_payloads}" + if i == message_limit - 1: + break - def test_valid_payloads_at_spam_rate(self): - self.setup_main_rln_relay_nodes() + def test_valid_payloads_at_spam_rate(self, pytestconfig): + message_limit = 20 + epoch_sec = 600 + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=message_limit, rln_relay_epoch_sec=epoch_sec) self.subscribe_main_relay_nodes() - previous = math.trunc(time()) - for i, payload in enumerate(SAMPLE_INPUTS[:5]): + start = math.trunc(time()) + for i, payload in enumerate(self.SAMPLE_INPUTS_RLN): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: + logger.debug(f"Sending message No. #{i + 1}") now = math.trunc(time()) self.publish_message(message) - # Skip for the first message (i > 0) - previous could be too apart from now - if i > 0 and (now - previous) == 0: + if i > message_limit and (now - start) <= epoch_sec: raise AssertionError("Publish with RLN enabled at spam rate worked!!!") - else: - previous = now except Exception as e: - assert "RLN validation failed" in str(e) + assert "RLN validation failed" or "NonceLimitReached" in str(e) - def test_valid_payload_at_variable_rate(self): - self.setup_main_rln_relay_nodes() + def test_valid_payload_at_variable_rate(self, pytestconfig): + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=1) self.subscribe_main_relay_nodes() payload_desc = SAMPLE_INPUTS[0]["description"] payload = to_base64(SAMPLE_INPUTS[0]["value"]) @@ -65,17 +92,19 @@ class TestRelayRLN(StepsRLN, StepsRelay): delay(1 + 1) now = math.trunc(time()) logger.debug(f"Message sent at timestamp {now}") + logger.debug(f"Sending message No. #{i + 1}") self.publish_message(message) if i > 0 and (now - previous) == 0: raise AssertionError("Publish with RLN enabled at spam rate worked!!!") else: previous = now except Exception as e: - assert "RLN validation failed" in str(e) + assert "RLN validation failed" or "NonceLimitReached" in str(e) - def test_valid_payloads_random_epoch_at_slow_rate(self): + def test_valid_payloads_random_epoch_at_slow_rate(self, pytestconfig): epoch_sec = random.randint(2, 5) - self.setup_main_rln_relay_nodes(rln_relay_epoch_sec=epoch_sec) + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=epoch_sec) self.subscribe_main_relay_nodes() failed_payloads = [] for payload in SAMPLE_INPUTS[:5]: @@ -89,10 +118,10 @@ class TestRelayRLN(StepsRLN, StepsRelay): delay(epoch_sec) assert not failed_payloads, f"Payloads failed: {failed_payloads}" - @pytest.mark.skip(reason="waiting for RLN v2 implementation") - def test_valid_payloads_random_user_message_limit(self): + def test_valid_payloads_random_user_message_limit(self, pytestconfig): user_message_limit = random.randint(2, 4) - self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=user_message_limit) + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=user_message_limit, rln_relay_epoch_sec=1) self.subscribe_main_relay_nodes() failed_payloads = [] for payload in SAMPLE_INPUTS[:user_message_limit]: @@ -105,110 +134,89 @@ class TestRelayRLN(StepsRLN, StepsRelay): failed_payloads.append(payload["description"]) assert not failed_payloads, f"Payloads failed: {failed_payloads}" - @pytest.mark.skip(reason="exceeding timeout, waiting for https://github.com/waku-org/nwaku/pull/2612 to be part of the release") @pytest.mark.timeout(600) - def test_valid_payloads_dynamic_at_slow_rate(self): - self.setup_main_rln_relay_nodes(rln_relay_dynamic="true", wait_for_node_sec=600) + def test_valid_payloads_dynamic_at_spam_rate(self, pytestconfig): + message_limit = 100 + epoch_sec = 600 + pytestconfig.cache.set("keystore-prefixes", self.register_rln_relay_nodes(2, [])) + self.setup_main_rln_relay_nodes( + rln_relay_user_message_limit=message_limit, + rln_relay_epoch_sec=epoch_sec, + rln_relay_dynamic="true", + wait_for_node_sec=600, + ) self.subscribe_main_relay_nodes() - failed_payloads = [] - for payload in SAMPLE_INPUTS: + start = math.trunc(time()) + for i, payload in enumerate(self.SAMPLE_INPUTS_RLN): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: + logger.debug(f"Sending message No. #{i + 1}") + now = math.trunc(time()) + self.publish_message(message) + if i > message_limit and (now - start) <= epoch_sec: + raise AssertionError("Publish with RLN enabled at spam rate worked!!!") + except Exception as e: + assert "RLN validation failed" or "NonceLimitReached" in str(e) + + @pytest.mark.timeout(600) + def test_valid_payloads_dynamic_at_slow_rate(self, pytestconfig): + message_limit = 100 + pytestconfig.cache.set("keystore-prefixes", self.register_rln_relay_nodes(2, [])) + self.setup_main_rln_relay_nodes( + rln_relay_user_message_limit=message_limit, + rln_relay_epoch_sec=600, + rln_relay_dynamic="true", + wait_for_node_sec=600, + ) + self.subscribe_main_relay_nodes() + failed_payloads = [] + for i, payload in enumerate(self.SAMPLE_INPUTS_RLN): + logger.debug(f'Running test with payload {payload["description"]}') + message = self.create_message(payload=to_base64(payload["value"])) + try: + logger.debug(f"Sending message No. #{i + 1}") self.check_published_message_reaches_relay_peer(message, message_propagation_delay=0.2) except Exception as e: logger.error(f'Payload {payload["description"]} failed: {str(e)}') failed_payloads.append(payload["description"]) delay(1) assert not failed_payloads, f"Payloads failed: {failed_payloads}" + if i == message_limit - 1: + break - @pytest.mark.skip(reason="exceeding timeout, waiting for https://github.com/waku-org/nwaku/pull/2612 to be part of the release") - @pytest.mark.timeout(600) - def test_valid_payloads_dynamic_at_spam_rate(self): - self.setup_main_rln_relay_nodes(rln_relay_dynamic="true", wait_for_node_sec=600) - self.subscribe_main_relay_nodes() - previous = math.trunc(time()) - for i, payload in enumerate(SAMPLE_INPUTS[:5]): - logger.debug(f'Running test with payload {payload["description"]}') - message = self.create_message(payload=to_base64(payload["value"])) - try: - now = math.trunc(time()) - self.publish_message(message) - if i > 0 and (now - previous) == 0: - raise AssertionError("Publish with RLN enabled at spam rate worked!!!") - else: - previous = now - except Exception as e: - assert "RLN validation failed" in str(e) - - def test_valid_payloads_n1_with_rln_n2_without_rln_at_spam_rate(self): - self.setup_first_rln_relay_node() + def test_valid_payloads_n1_with_rln_n2_without_rln_at_spam_rate(self, pytestconfig): + message_limit = 1 + epoch_sec = 1 + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_first_rln_relay_node(rln_relay_user_message_limit=message_limit, rln_relay_epoch_sec=epoch_sec) self.setup_second_relay_node() self.subscribe_main_relay_nodes() - previous = math.trunc(time()) + start = math.trunc(time()) for i, payload in enumerate(SAMPLE_INPUTS[:5]): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: now = math.trunc(time()) self.publish_message(message) - if i > 0 and (now - previous) == 0: + if i > message_limit and (now - start) <= epoch_sec: raise AssertionError("Publish with RLN enabled at spam rate worked!!!") - else: - previous = now except Exception as e: - assert "RLN validation failed" in str(e) - - @pytest.mark.skip(reason="Epoch settings aren't compatible across nodes") - def test_valid_payloads_mixed_epoch_at_slow_rate(self): - n1_epoch_sec = 5 - n2_epoch_sec = 1 - self.setup_first_rln_relay_node(rln_relay_epoch_sec=n1_epoch_sec) - self.setup_second_rln_relay_node(rln_relay_epoch_sec=n2_epoch_sec) - self.subscribe_main_relay_nodes() - failed_payloads = [] - for payload in SAMPLE_INPUTS[:5]: - logger.debug(f'Running test with payload {payload["description"]}') - message = self.create_message(payload=to_base64(payload["value"])) - try: - self.check_published_message_reaches_relay_peer(message, message_propagation_delay=0.2) - except Exception as e: - logger.error(f'Payload {payload["description"]} failed: {str(e)}') - failed_payloads.append(payload["description"]) - delay(n1_epoch_sec) - assert not failed_payloads, f"Payloads failed: {failed_payloads}" - - @pytest.mark.skip(reason="waiting for NWAKU lightpush + RLN node implementation") - def test_valid_payloads_lightpush_at_spam_rate(self): - self.setup_first_rln_relay_node(lightpush="true") - self.setup_second_lightpush_node() - self.subscribe_main_relay_nodes() - previous = math.trunc(time()) - for i, payload in enumerate(SAMPLE_INPUTS[:5]): - logger.debug(f'Running test with payload {payload["description"]}') - message = self.create_message(payload=to_base64(payload["value"])) - try: - now = math.trunc(time()) - self.publish_message(message=message, sender=self.light_push_node2, use_lightpush=True) - if i > 0 and (now - previous) == 0: - raise AssertionError("Publish with RLN enabled at spam rate worked!!!") - else: - previous = now - except Exception as e: - assert "RLN validation failed" in str(e) + assert "RLN validation failed" or "NonceLimitReached" in str(e) @pytest.mark.skipif("go-waku" in ADDITIONAL_NODES, reason="Test works only with nwaku") - @pytest.mark.usefixtures("register_main_rln_relay_nodes", "register_optional_rln_relay_nodes") - def test_valid_payloads_with_optional_nodes_at_slow_rate(self): - self.setup_main_rln_relay_nodes() - self.setup_optional_rln_relay_nodes() + def test_valid_payloads_with_optional_nodes_at_slow_rate(self, pytestconfig): + pytestconfig.cache.set("keystore-prefixes", self.register_rln_relay_nodes(5, [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=1) + self.setup_optional_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=1) self.subscribe_main_relay_nodes() self.subscribe_optional_relay_nodes() failed_payloads = [] - for payload in SAMPLE_INPUTS: + for i, payload in enumerate(SAMPLE_INPUTS): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: + logger.debug(f"Sending message No. #{i + 1}") self.check_published_message_reaches_relay_peer(message, message_propagation_delay=0.2) except Exception as e: logger.error(f'Payload {payload["description"]} failed: {str(e)}') @@ -217,10 +225,10 @@ class TestRelayRLN(StepsRLN, StepsRelay): assert not failed_payloads, f"Payloads failed: {failed_payloads}" @pytest.mark.skipif("go-waku" in ADDITIONAL_NODES, reason="Test works only with nwaku") - @pytest.mark.usefixtures("register_main_rln_relay_nodes", "register_optional_rln_relay_nodes") - def test_valid_payloads_with_optional_nodes_at_spam_rate(self): - self.setup_main_rln_relay_nodes() - self.setup_optional_rln_relay_nodes() + def test_valid_payloads_with_optional_nodes_at_spam_rate(self, pytestconfig): + self.register_rln_relay_nodes(0, pytestconfig.cache.get("keystore-prefixes", [])) + self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=1) + self.setup_optional_rln_relay_nodes(rln_relay_user_message_limit=1, rln_relay_epoch_sec=1) self.subscribe_main_relay_nodes() self.subscribe_optional_relay_nodes() previous = math.trunc(time()) @@ -228,6 +236,7 @@ class TestRelayRLN(StepsRLN, StepsRelay): logger.debug(f'Running test with payload {payload["description"]}') message = self.create_message(payload=to_base64(payload["value"])) try: + logger.debug(f"Sending message No. #{i + 1}") now = math.trunc(time()) self.publish_message(message) if i > 0 and (now - previous) == 0: @@ -235,4 +244,4 @@ class TestRelayRLN(StepsRLN, StepsRelay): else: previous = now except Exception as e: - assert "RLN validation failed" in str(e) + assert "RLN validation failed" or "NonceLimitReached" in str(e)