chore: RLN relay tests (#30)

* fix: add get_multiaddr_with_id step
- temporarily use local docker images

* fix: discard containers used for RLN registration

* fix: switch to use cluster ID 1 for RLN

* test: publish at slow and spam rate

* fix: shorten test data set

* fix: move RLN related code into separate class

* fix: use send only publish function
- add spam and alternate rate tests

* fix: use math.trunc instead of rounding

* fix: first message without delay

* fix: add one more second to messages with delay

* fix: add methods to setup non default RLN nodes

* fix: rewrite tests using steps rather than fixtures
- prepare for non default settings for RLN

* test: random epoch with valid_payloads_at_slow_rate

* test: random user message limit with valid payloads

* fix: skip test "random user message limit with valid payloads"

* fix: mark flaky "at variable_rate with valid payloads"

* fix: rename tests for easier debugging

* fix: mark valid_payloads_dynamic_at_slow_rate to skip

* fix: forgot to add actual file

* test: valid payloads dynamic(on chain) at spam rate
- extend timeout for ensure_ready() to 600s
- add ensure_healthy() for future use
- add text content based rest call
- remove NODE1, NODE2 imports

* fix: revert env_vars to source images from Harbor

* fix: reuse setup first and second rln relay node for setup_main_rln_relay_nodes

* fix: reuse register_rln_single_node for register_main_rln_relay_nodes

* fix: start using src.steps.common
- removed RLN test class inheritance from StepsRelay

* fix: test using whole data set at test payloads_at_slow_rate

* fix: switch to send msg and check for slow rate tests

* fix: add comment for skip check at first message

* fix: refactor payloads_at_variable_rate to use only one payload pattern

* fix: remove the plural from payloads_at_variable_rate

* fix: multiple class inheritance for TestRelayRLN

* test: node1 with rln node2 without rln at spam rate

* test: mixed epoch at slow rate

* test: add lightpush methods

* test: send valid payloads lightpush at spam rate

* fix: node1 to act as light push receiving node
- add setup lightpush node to spin off node2 with lightpush support

* fix: use NODE1 NODE2 instead of DEFAULT_NWAKU

* fix: no lightpush param required for plain RLN relay

* fix: comment for lightpush

* fix: comment for lightpush - wait for implementation

* fix: comment on chain tests

* fix: add lightpush case to publish_message

* fix: remove check_light_pushed_message_reaches_receiving_peer from StepsRLN

* fix: change comment for mixed_epoch_at_slow_rate

* test: happy and common case with 5 nodes

* fix: add all required fixtures explicitly

* fix: add timeout param to ensure_ready

* fix: skip RLN tests for go-waku

* fix: reformated with pre-commit

* fix: uncomment skip for debugging

* fix: put the skip back

* fix: change comment for on chain tests

* fix: run RLN tests in serial
- add grouping of tests to runner
- use smaller dataset for spam rate tests

* test: Nim to Nim workflow

* test: check also additional nodes for go-waku

* test: all nodes are nwaku

* fix: string quotes

* fix: remove additional nodes

* fix: re-arrange skip conditions

* test: RLN only

* fix: change default additional nodes to nwaku only

* fix: change additional nodes rather at top level workflow

* fix: enable all tests

* test: problems with current workdir

* test: rln only

* test: correct typo

* test: re-enable all tests
- remove current dir debug

* fix: nwaku additional nodes for nim to nim worklfow

* fix: re-able discord notification
- delete test workflow

* fix: add get_multiaddr_with_id step
- temporarily use local docker images

* fix: discard containers used for RLN registration

* fix: switch to use cluster ID 1 for RLN

* test: publish at slow and spam rate

* fix: shorten test data set

* fix: rebase onto master

* fix: use send only publish function
- add spam and alternate rate tests

* fix: use math.trunc instead of rounding

* fix: first message without delay

* fix: add one more second to messages with delay

* fix: add methods to setup non default RLN nodes

* fix: rewrite tests using steps rather than fixtures
- prepare for non default settings for RLN

* test: random epoch with valid_payloads_at_slow_rate

* test: random user message limit with valid payloads

* fix: skip test "random user message limit with valid payloads"

* fix: mark flaky "at variable_rate with valid payloads"

* fix: rename tests for easier debugging

* fix: mark valid_payloads_dynamic_at_slow_rate to skip

* fix: forgot to add actual file

* test: valid payloads dynamic(on chain) at spam rate
- extend timeout for ensure_ready() to 600s
- add ensure_healthy() for future use
- add text content based rest call
- remove NODE1, NODE2 imports

* fix: revert env_vars to source images from Harbor

* fix: reuse setup first and second rln relay node for setup_main_rln_relay_nodes

* fix: reuse register_rln_single_node for register_main_rln_relay_nodes

* fix: start using src.steps.common
- removed RLN test class inheritance from StepsRelay

* fix: test using whole data set at test payloads_at_slow_rate

* fix: switch to send msg and check for slow rate tests

* fix: add comment for skip check at first message

* fix: refactor payloads_at_variable_rate to use only one payload pattern

* fix: remove the plural from payloads_at_variable_rate

* fix: multiple class inheritance for TestRelayRLN

* test: node1 with rln node2 without rln at spam rate

* test: mixed epoch at slow rate

* test: add lightpush methods

* test: send valid payloads lightpush at spam rate

* fix: node1 to act as light push receiving node
- add setup lightpush node to spin off node2 with lightpush support

* fix: use NODE1 NODE2 instead of DEFAULT_NWAKU

* fix: no lightpush param required for plain RLN relay

* fix: comment for lightpush

* fix: comment for lightpush - wait for implementation

* fix: comment on chain tests

* fix: add lightpush case to publish_message

* fix: remove check_light_pushed_message_reaches_receiving_peer from StepsRLN

* fix: change comment for mixed_epoch_at_slow_rate

* test: happy and common case with 5 nodes

* fix: add all required fixtures explicitly

* fix: add timeout param to ensure_ready

* fix: skip RLN tests for go-waku

* fix: uncomment skip for debugging

* fix: put the skip back

* fix: change comment for on chain tests

* fix: run RLN tests in serial
- add grouping of tests to runner
- use smaller dataset for spam rate tests

* test: Nim to Nim workflow

* test: check also additional nodes for go-waku

* test: all nodes are nwaku

* fix: string quotes

* fix: remove additional nodes

* fix: re-arrange skip conditions

* test: RLN only

* fix: change default additional nodes to nwaku only

* fix: change additional nodes rather at top level workflow

* fix: enable all tests

* test: problems with current workdir

* test: rln only

* test: correct typo

* test: re-enable all tests
- remove current dir debug

* fix: nwaku additional nodes for nim to nim worklfow

* fix: re-able discord notification
- delete test workflow

* test: re-test again after rebase

* fix: wait longer for credential store

* test: try again with Discord report off

* fix: enable Discord
- delete test workflow
This commit is contained in:
Roman Zajic 2024-05-07 08:31:12 +08:00 committed by GitHub
parent edb1f59448
commit 151233fddb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 441 additions and 65 deletions

View File

@ -16,4 +16,5 @@ jobs:
with:
node1: "harbor.status.im/wakuorg/nwaku:latest"
node2: "harbor.status.im/wakuorg/nwaku:latest"
additional_nodes: "harbor.status.im/wakuorg/nwaku:latest,harbor.status.im/wakuorg/nwaku:latest,harbor.status.im/wakuorg/nwaku:latest"
caller: "nim"

View File

@ -49,7 +49,8 @@ jobs:
- run: pip install -r requirements.txt
- name: Run tests
run: pytest -n 4 --reruns 2 --alluredir=allure-results
run: |
pytest -n 4 --dist loadgroup --reruns 2 --alluredir=allure-results
- name: Get allure history
if: always()

View File

@ -15,10 +15,19 @@ class REST(BaseClient):
headers = {"Content-Type": "application/json"}
return self.make_request(method, url, headers=headers, data=payload)
def rest_call_text(self, method, endpoint, payload=None):
url = f"http://127.0.0.1:{self._rest_port}/{endpoint}"
headers = {"accept": "text/plain"}
return self.make_request(method, url, headers=headers, data=payload)
def info(self):
info_response = self.rest_call("get", "debug/v1/info")
return info_response.json()
def health(self):
health_response = self.rest_call_text("get", "health")
return health_response.text()
def get_peers(self):
get_peers_response = self.rest_call("get", "admin/v1/peers")
return get_peers_response.json()

View File

@ -31,7 +31,7 @@ def sanitize_docker_flags(input_flags):
return output_flags
@retry(stop=stop_after_delay(120), wait=wait_fixed(0.5), reraise=True)
@retry(stop=stop_after_delay(180), wait=wait_fixed(0.5), reraise=True)
def rln_credential_store_ready(creds_file_path):
if os.path.exists(creds_file_path):
return True
@ -48,7 +48,7 @@ class WakuNode:
logger.debug(f"WakuNode instance initialized with log path {self._log_path}")
@retry(stop=stop_after_delay(5), wait=wait_fixed(0.1), reraise=True)
def start(self, **kwargs):
def start(self, wait_for_node_sec=10, **kwargs):
logger.debug("Starting Node...")
self._docker_manager.create_network()
self._ext_ip = self._docker_manager.generate_random_ext_ip()
@ -113,6 +113,8 @@ class WakuNode:
else:
logger.info(f"RLN credentials not set or credential store not available, starting without RLN")
logger.debug(f"Using volumes {self._volumes}")
self._container = self._docker_manager.start_container(
self._docker_manager.image, self._ports, default_args, self._log_path, self._ext_ip, self._volumes
)
@ -121,7 +123,7 @@ class WakuNode:
DS.waku_nodes.append(self)
delay(1) # if we fire requests to soon after starting the node will sometimes fail to start correctly
try:
self.ensure_ready()
self.ensure_ready(timeout_duration=wait_for_node_sec)
except Exception as ex:
logger.error(f"REST service did not become ready in time: {ex}")
raise
@ -184,10 +186,18 @@ class WakuNode:
logger.debug(f"Unpause container with id {self._container.short_id}")
self._container.unpause()
@retry(stop=stop_after_delay(10), wait=wait_fixed(0.1), reraise=True)
def ensure_ready(self):
self.info_response = self.info()
logger.info("REST service is ready !!")
def ensure_ready(self, timeout_duration=10):
@retry(stop=stop_after_delay(timeout_duration), wait=wait_fixed(0.1), reraise=True)
def check_ready(node=self):
node.info_response = node.info()
logger.info("REST service is ready !!")
check_ready()
@retry(stop=stop_after_delay(10), wait=wait_fixed(1), reraise=True)
def ensure_healthy(self):
self.health_response = self.health()
logger.info("Node is healthy !!")
def get_enr_uri(self):
try:
@ -208,6 +218,9 @@ class WakuNode:
def info(self):
return self._api.info()
def health(self):
return self._api.health()
def get_peers(self):
return self._api.get_peers()

View File

@ -1,20 +1,17 @@
import inspect
import os
from src.libs.custom_logger import get_custom_logger
from time import time
import pytest
import allure
from src.libs.common import to_base64, delay, gen_step_id
from src.libs.common import to_base64, delay
from src.node.waku_message import WakuMessage
from src.env_vars import (
NODE_1,
NODE_2,
ADDITIONAL_NODES,
NODEKEY,
DEFAULT_NWAKU,
RLN_CREDENTIALS,
)
from src.node.waku_node import WakuNode, rln_credential_store_ready
from src.node.waku_node import WakuNode
from tenacity import retry, stop_after_delay, wait_fixed
from src.steps.common import StepsCommon
from src.test_data import VALID_PUBSUB_TOPICS
@ -45,28 +42,6 @@ class StepsRelay(StepsCommon):
self.add_node_peer(self.node2, [self.multiaddr_with_id])
self.main_nodes.extend([self.node1, self.node2])
@pytest.fixture(scope="function")
def register_main_rln_relay_nodes(self, request):
logger.debug(f"Registering RLN credentials: {inspect.currentframe().f_code.co_name}")
self.node1 = WakuNode(DEFAULT_NWAKU, f"node1_{request.cls.test_id}")
self.node1.register_rln(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="1")
self.node2 = WakuNode(DEFAULT_NWAKU, f"node2_{request.cls.test_id}")
self.node2.register_rln(rln_creds_source=RLN_CREDENTIALS, rln_creds_id="2")
self.main_nodes.extend([self.node1, self.node2])
@pytest.fixture(scope="function")
def setup_main_rln_relay_nodes(self, request):
logger.debug(f"Running fixture setup: {inspect.currentframe().f_code.co_name}")
self.node1 = WakuNode(DEFAULT_NWAKU, f"node1_{request.cls.test_id}")
self.node1.start(relay="true", nodekey=NODEKEY, rln_creds_source=RLN_CREDENTIALS, rln_creds_id="1", rln_relay_membership_index="1")
self.enr_uri = self.node1.get_enr_uri()
self.node2 = WakuNode(DEFAULT_NWAKU, f"node2_{request.cls.test_id}")
self.node2.start(
relay="true", discv5_bootstrap_node=self.enr_uri, rln_creds_source=RLN_CREDENTIALS, rln_creds_id="2", rln_relay_membership_index="1"
)
self.add_node_peer(self.node2, [self.multiaddr_with_id])
self.main_nodes.extend([self.node1, self.node2])
@pytest.fixture(scope="function")
def setup_optional_relay_nodes(self, request):
logger.debug(f"Running fixture setup: {inspect.currentframe().f_code.co_name}")
@ -156,19 +131,3 @@ class StepsRelay(StepsCommon):
def subscribe_and_publish_with_retry(self, node_list, pubsub_topic_list):
self.ensure_relay_subscriptions_on_nodes(node_list, pubsub_topic_list)
self.check_published_message_reaches_relay_peer()
@allure.step
def register_rln_single_node(self, **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"])
@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"
try:
rln_credential_store_ready(creds_file_path)
except Exception as ex:
logger.error(f"Credentials at {creds_file_path} not available: {ex}")
raise

178
src/steps/rln.py Normal file
View File

@ -0,0 +1,178 @@
import os
import inspect
import pytest
import allure
from src.node.waku_message import WakuMessage
from src.steps.common import StepsCommon
from src.test_data import PUBSUB_TOPICS_RLN
from src.env_vars import DEFAULT_NWAKU, RLN_CREDENTIALS, NODEKEY, NODE_1, NODE_2, ADDITIONAL_NODES
from src.libs.common import gen_step_id, delay
from src.libs.custom_logger import get_custom_logger
from src.node.waku_node import WakuNode, rln_credential_store_ready
logger = get_custom_logger(__name__)
class StepsRLN(StepsCommon):
test_pubsub_topic = PUBSUB_TOPICS_RLN[0]
test_content_topic = "/test/1/waku-rln-relay/proto"
test_payload = "RLN relay works!!"
main_nodes = []
optional_nodes = []
multiaddr_list = []
lightpush_nodes = []
@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")
@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")
@allure.step
def setup_main_rln_relay_nodes(self, **kwargs):
self.setup_first_rln_relay_node(**kwargs)
self.setup_second_rln_relay_node(**kwargs)
@allure.step
def setup_first_rln_relay_node(self, **kwargs):
self.node1 = WakuNode(NODE_1, f"node1_{self.test_id}")
self.node1.start(
relay="true",
nodekey=NODEKEY,
rln_creds_source=RLN_CREDENTIALS,
rln_creds_id="1",
rln_relay_membership_index="1",
**kwargs,
)
self.enr_uri = self.node1.get_enr_uri()
self.multiaddr_with_id = self.node1.get_multiaddr_with_id()
self.main_nodes.extend([self.node1])
self.multiaddr_list.extend([self.node1.get_multiaddr_with_id()])
@allure.step
def setup_second_rln_relay_node(self, **kwargs):
self.node2 = WakuNode(NODE_2, f"node2_{self.test_id}")
self.node2.start(
relay="true",
discv5_bootstrap_node=self.enr_uri,
rln_creds_source=RLN_CREDENTIALS,
rln_creds_id="2",
rln_relay_membership_index="1",
**kwargs,
)
self.add_node_peer(self.node2, [self.multiaddr_with_id])
self.main_nodes.extend([self.node2])
@allure.step
def setup_optional_rln_relay_nodes(self, **kwargs):
if ADDITIONAL_NODES:
nodes = [node.strip() for node in ADDITIONAL_NODES.split(",")]
else:
pytest.skip("ADDITIONAL_NODES is empty, cannot run test")
if len(nodes) > 3:
logger.debug("More than 3 nodes are not supported for RLN tests, using first 3")
nodes = nodes[:3]
for index, node in enumerate(nodes):
node = WakuNode(node, f"node{index + 3}_{self.test_id}")
node.start(
relay="true",
discv5_bootstrap_node=self.enr_uri,
rln_creds_source=RLN_CREDENTIALS,
rln_creds_id=f"{index + 3}",
rln_relay_membership_index="1",
**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):
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)
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 setup_first_relay_node(self, **kwargs):
self.node1 = WakuNode(NODE_1, f"node1_{self.test_id}")
self.node1.start(relay="true", nodekey=NODEKEY, **kwargs)
self.enr_uri = self.node1.get_enr_uri()
self.multiaddr_with_id = self.node1.get_multiaddr_with_id()
self.main_nodes.extend([self.node1])
@allure.step
def setup_second_relay_node(self, **kwargs):
self.node2 = WakuNode(NODE_2, f"node2_{self.test_id}")
self.node2.start(
relay="true",
discv5_bootstrap_node=self.enr_uri,
**kwargs,
)
self.add_node_peer(self.node2, [self.multiaddr_with_id])
self.main_nodes.extend([self.node2])
@allure.step
def register_rln_single_node(self, **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"])
@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"
try:
rln_credential_store_ready(creds_file_path)
except Exception as ex:
logger.error(f"Credentials at {creds_file_path} not available: {ex}")
raise
@allure.step
def publish_message(self, message=None, pubsub_topic=None, sender=None, use_lightpush=False):
if message is None:
message = self.create_message()
if pubsub_topic is None:
pubsub_topic = self.test_pubsub_topic
if not sender:
sender = self.node1
if use_lightpush:
payload = self.create_payload(pubsub_topic, message)
sender.send_light_push_message(payload)
else:
sender.send_relay_message(message, pubsub_topic)
@allure.step
def ensure_relay_subscriptions_on_nodes(self, node_list, pubsub_topic_list):
for node in node_list:
node.set_relay_subscriptions(pubsub_topic_list)
@allure.step
def subscribe_main_relay_nodes(self):
self.ensure_relay_subscriptions_on_nodes(self.main_nodes, [self.test_pubsub_topic])
@allure.step
def subscribe_optional_relay_nodes(self):
self.ensure_relay_subscriptions_on_nodes(self.optional_nodes, [self.test_pubsub_topic])
@allure.step
def create_payload(self, pubsub_topic=None, message=None, **kwargs):
if message is None:
message = self.create_message()
if pubsub_topic is None:
pubsub_topic = self.test_pubsub_topic
payload = {"pubsubTopic": pubsub_topic, "message": message}
payload.update(kwargs)
return payload

View File

@ -148,3 +148,5 @@ SAMPLE_TIMESTAMPS = [
{"description": "ISO 8601 timestamp", "value": "2023-12-26T10:58:51", "valid_for": []},
{"description": "Missing", "value": None, "valid_for": ["gowaku"]},
]
PUBSUB_TOPICS_RLN = ["/waku/2/rs/1/0"]

View File

@ -1,24 +1,237 @@
import os
import math
import random
from time import time
import pytest
from src.env_vars import RLN_CREDENTIALS
from src.env_vars import NODE_1, NODE_2, ADDITIONAL_NODES
from src.libs.common import delay, to_base64
from src.libs.custom_logger import get_custom_logger
from src.steps.relay import StepsRelay
from src.steps.rln import StepsRLN
from src.test_data import SAMPLE_INPUTS
logger = get_custom_logger(__name__)
@pytest.mark.usefixtures()
class TestRelayRLN(StepsRelay):
def test_register_rln(self):
logger.debug("Running register RLN test for main relay nodes")
key_stores_found = 0
@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")
class TestRelayRLN(StepsRLN, StepsRelay):
def test_valid_payloads_at_slow_rate(self):
self.setup_main_rln_relay_nodes()
self.subscribe_main_relay_nodes()
failed_payloads = []
for payload in SAMPLE_INPUTS:
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)
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 RLN_CREDENTIALS is None:
pytest.skip("RLN_CREDENTIALS not set, skipping test")
def test_valid_payloads_at_spam_rate(self):
self.setup_main_rln_relay_nodes()
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)
# Skip for the first message (i > 0) - previous could be too apart from now
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)
for k in range(1, 6):
self.register_rln_single_node(rln_creds_source=RLN_CREDENTIALS, rln_creds_id=f"{k}")
self.check_rln_registration(k)
key_stores_found += 1
assert key_stores_found == 5, f"Invalid number of RLN keystores found, expected 5 found {key_stores_found}"
def test_valid_payload_at_variable_rate(self):
self.setup_main_rln_relay_nodes()
self.subscribe_main_relay_nodes()
payload_desc = SAMPLE_INPUTS[0]["description"]
payload = to_base64(SAMPLE_INPUTS[0]["value"])
previous = math.trunc(time())
for i in range(0, 10):
logger.debug(f"Running test with payload {payload_desc}")
message = self.create_message(payload=payload)
try:
if i % 2 == 1: # every odd iteration is sent slowly
delay(1 + 1)
now = math.trunc(time())
logger.debug(f"Message sent at timestamp {now}")
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_random_epoch_at_slow_rate(self):
epoch_sec = random.randint(2, 5)
self.setup_main_rln_relay_nodes(rln_relay_epoch_sec=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)
except Exception as e:
logger.error(f'Payload {payload["description"]} failed: {str(e)}')
failed_payloads.append(payload["description"])
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):
user_message_limit = random.randint(2, 4)
self.setup_main_rln_relay_nodes(rln_relay_user_message_limit=user_message_limit)
self.subscribe_main_relay_nodes()
failed_payloads = []
for payload in SAMPLE_INPUTS[:user_message_limit]:
logger.debug(f'Running test with payload {payload["description"]}')
message = self.create_message(payload=to_base64(payload["value"]))
try:
self.publish_message(message)
except Exception as e:
logger.error(f'Payload {payload["description"]} failed: {str(e)}')
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)
self.subscribe_main_relay_nodes()
failed_payloads = []
for payload in SAMPLE_INPUTS:
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)
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}"
@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()
self.setup_second_relay_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)
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)
@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)
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)
@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()
self.subscribe_main_relay_nodes()
self.subscribe_optional_relay_nodes()
failed_payloads = []
for payload in SAMPLE_INPUTS:
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)
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}"
@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()
self.subscribe_main_relay_nodes()
self.subscribe_optional_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)