From ec86cc47756f2cdd4ba084af432f7592fb655799 Mon Sep 17 00:00:00 2001 From: Ivan FB <128452529+Ivansete-status@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:47:35 +0200 Subject: [PATCH] ci: fix Nim checksum mismatch when building liblogosdelivery (#188) * Add docker mark for docker nodes tests * Add the ports allocation tests * trigger CI job * update the .so * chore: update logos-delivery-python-bindings * bump bindings submodule for fresh CI build * bump bindings to pull in logos-delivery #3828 * ci: pin nimble 0.22.3 to fix Nim checksum mismatch on liblogosdelivery build The "Build liblogosdelivery.so" job ran a bare `nimble install -y` inside the logos-delivery checkout, resolving the package's locked deps with whatever nimble choosenim ships. That nimble recomputes the locked Nim package checksum differently from the nimble that generated nimble.lock (0.22.3), so the build aborted with: Downloaded package checksum does not correspond to that in the lock file: Package: nim@v.2.2.4@r.911e0dbb... Expected checksum: 68bb85cb... Mirror logos-delivery's own CI: pin nimble 0.22.3 after installing Nim, and drop the redundant `nimble install -y` / no-op `make setup`. `make liblogosdelivery` already resolves the locked deps via its build-deps prerequisite (`nimble setup --localdeps`). Co-Authored-By: Claude Opus 4.8 * Bump bindings submodule to pull in logos-delivery latest master Points vendor/logos-delivery-python-bindings at the bump-logos-delivery-master branch (logos-delivery-python-bindings#6), which advances logos-delivery to master 4099ff26. Merge that bindings PR before this one so the pointer lands on bindings master. Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Aya Hassan Co-authored-by: Claude Opus 4.8 Co-authored-by: AYAHASSAN287 <49167455+AYAHASSAN287@users.noreply.github.com> --- .github/workflows/pr_tests.yml | 26 +++-- .../test_send_lightpush_and_edge.py | 2 + .../test_wrapper_corner_cases.py | 96 +++++++++++++++++++ vendor/logos-delivery-python-bindings | 2 +- 4 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 tests/wrappers_tests/test_wrapper_corner_cases.py diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index d9948c8e3..040d49a87 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -44,7 +44,7 @@ jobs: run: | BINDINGS_HASH=$(git rev-parse HEAD:vendor/logos-delivery-python-bindings) DELIVERY_HASH=$(git -C vendor/logos-delivery-python-bindings rev-parse HEAD:vendor/logos-delivery) - echo "key=liblogosdelivery-${{ runner.os }}-nim2.2.4-${BINDINGS_HASH}-${DELIVERY_HASH}" >> "$GITHUB_OUTPUT" + echo "key=liblogosdelivery-${{ runner.os }}-nim2.2.4-v2-${BINDINGS_HASH}-${DELIVERY_HASH}" >> "$GITHUB_OUTPUT" - name: Cache liblogosdelivery.so id: cache-lib @@ -71,7 +71,7 @@ jobs: gcc \ g++ - - name: Install Nim 2.2.4 + - name: Install Nim 2.2.4 and Nimble 0.22.3 if: steps.cache-lib.outputs.cache-hit != 'true' run: | set -euo pipefail @@ -79,6 +79,10 @@ jobs: echo "$HOME/.nimble/bin" >> "$GITHUB_PATH" export PATH="$HOME/.nimble/bin:$PATH" choosenim 2.2.4 + # Pin the nimble that generated logos-delivery's nimble.lock. A newer + # nimble recomputes the locked Nim package checksum differently, which + # makes `nimble setup --localdeps` abort with a checksum mismatch. + (cd /tmp && nimble install "nimble@0.22.3" -y) nim --version nimble --version @@ -98,10 +102,10 @@ jobs: ln -sf waku.nimble waku.nims - nimble install -y - - make setup - + # `make liblogosdelivery` resolves the locked deps via + # `nimble setup --localdeps` (build-deps prerequisite); a bare + # `nimble install -y` here is redundant and pulls Nim from the lock, + # which is what triggered the checksum mismatch. make liblogosdelivery SO_PATH="$(find . -type f -name 'liblogosdelivery.so' | head -n 1)" @@ -199,6 +203,16 @@ jobs: --reruns 2 \ --junit-xml=wrapper-results-send-errors-and-concurrency.xml + - name: Run wrapper tests - corner cases + continue-on-error: true + env: + PYTHONPATH: ${{ github.workspace }}/vendor/logos-delivery-python-bindings/waku + run: | + pytest tests/wrappers_tests/test_wrapper_corner_cases.py \ + -m "not docker_required" \ + --reruns 2 \ + --junit-xml=wrapper-results-corner-cases.xml + - name: Test Report if: always() uses: dorny/test-reporter@95058abb17504553158e70e2c058fe1fda4392c2 diff --git a/tests/wrappers_tests/test_send_lightpush_and_edge.py b/tests/wrappers_tests/test_send_lightpush_and_edge.py index d22568df5..507dbbed5 100644 --- a/tests/wrappers_tests/test_send_lightpush_and_edge.py +++ b/tests/wrappers_tests/test_send_lightpush_and_edge.py @@ -292,6 +292,7 @@ class TestS11EdgeSenderLightpushAndStore(StepsCommon): store node (cross-implementation check). """ + @pytest.mark.docker_required def test_s11_edge_lightpush_with_store_validation(self): sender_collector = EventCollector() @@ -929,6 +930,7 @@ class TestS25EphemeralLightpushWithStore(StepsCommon): staticnodes=[lightpush_peer, store_peer] """ + @pytest.mark.docker_required def test_s25_ephemeral_lightpush_with_store(self): sender_collector = EventCollector() diff --git a/tests/wrappers_tests/test_wrapper_corner_cases.py b/tests/wrappers_tests/test_wrapper_corner_cases.py new file mode 100644 index 000000000..8aa7d639a --- /dev/null +++ b/tests/wrappers_tests/test_wrapper_corner_cases.py @@ -0,0 +1,96 @@ +import re +import pytest +from src.steps.common import StepsCommon +from src.libs.custom_logger import get_custom_logger +from src.node.wrappers_manager import WrapperManager +from src.node.wrapper_helpers import ( + EventCollector, + create_message_bindings, + get_node_multiaddr, + wait_for_propagated, +) +from tests.wrappers_tests.conftest import build_node_config + +logger = get_custom_logger(__name__) + +PROPAGATED_TIMEOUT_S = 30.0 + +# Matches the /tcp// segment in a libp2p multiaddr. +TCP_PORT_RE = re.compile(r"/tcp/(\d+)/") + + +def _extract_tcp_port(multiaddr: str) -> int: + match = TCP_PORT_RE.search(multiaddr) + assert match, f"multiaddr missing /tcp// segment: {multiaddr!r}" + return int(match.group(1)) + + +class TestWrapperAutoPortAllocation(StepsCommon): + """Corner case: port 0 triggers auto-port allocation. + + Tracks logos-messaging/logos-delivery#3828. Per that PR, auto-port is + opt-in (caller passes 0 explicitly) and only applies to tcpPort, + discv5UdpPort and webSocketPort. restPort and metricsServerPort still + require a concrete value, so they are not exercised here. + """ + + def test_auto_port_starts_node_with_tcp_and_discv5_zero(self): + config = build_node_config(tcpPort=0, discv5UdpPort=0) + + result = WrapperManager.create_and_start(config=config) + assert result.is_ok(), f"create_and_start failed with tcpPort=0, discv5UdpPort=0: " f"{result.err()}" + + with result.ok_value as node: + multiaddr = get_node_multiaddr(node) + tcp_port = _extract_tcp_port(multiaddr) + + assert tcp_port != 0, f"multiaddr still reports tcp port 0; auto-port did not " f"happen. multiaddr={multiaddr!r}" + assert 1024 <= tcp_port <= 65535, f"auto-allocated tcp port out of range: {tcp_port} " f"(multiaddr={multiaddr!r})" + + def test_auto_port_node_can_propagate_message(self): + # End-to-end: two nodes, sender uses auto-port for tcp + discv5. + # restPort stays concrete because REST does not support auto-port. + sender_collector = EventCollector() + sender_config = build_node_config(tcpPort=0, discv5UdpPort=0) + + sender_result = WrapperManager.create_and_start( + config=sender_config, + event_cb=sender_collector.event_callback, + ) + assert sender_result.is_ok(), f"sender start failed: {sender_result.err()}" + + with sender_result.ok_value as sender: + sender_addr = get_node_multiaddr(sender) + + peer_config = build_node_config( + tcpPort=0, + discv5UdpPort=0, + staticnodes=[sender_addr], + ) + peer_result = WrapperManager.create_and_start(config=peer_config) + assert peer_result.is_ok(), f"peer start failed: {peer_result.err()}" + + with peer_result.ok_value: + message = create_message_bindings() + send_result = sender.send_message(message=message) + assert send_result.is_ok(), f"send failed: {send_result.err()}" + + request_id = send_result.ok_value + assert request_id, "send returned empty RequestId" + + propagated = wait_for_propagated(sender_collector, request_id, PROPAGATED_TIMEOUT_S) + assert propagated is not None, f"no message_propagated with auto-allocated ports. " f"Events: {sender_collector.events}" + + @pytest.mark.parametrize("port_field", ["tcpPort", "discv5UdpPort"]) + def test_auto_port_per_field(self, port_field): + # Each auto-port-capable field set to 0 in isolation. restPort and + # metricsServerPort are intentionally excluded (see class docstring). + config = build_node_config(**{port_field: 0}) + + result = WrapperManager.create_and_start(config=config) + assert result.is_ok(), f"create_and_start failed with {port_field}=0: {result.err()}" + + with result.ok_value as node: + multiaddr = get_node_multiaddr(node) + tcp_port = _extract_tcp_port(multiaddr) + assert tcp_port != 0, f"tcp port is 0 in multiaddr with {port_field}=0; " f"multiaddr={multiaddr!r}" diff --git a/vendor/logos-delivery-python-bindings b/vendor/logos-delivery-python-bindings index 370693695..36041dae7 160000 --- a/vendor/logos-delivery-python-bindings +++ b/vendor/logos-delivery-python-bindings @@ -1 +1 @@ -Subproject commit 370693695f8843a26108aa34c915bf6bd9f9f2d5 +Subproject commit 36041dae76a53fff91fe53253933d8eb2ab385f9