Merge remote-tracking branch 'origin/master' into feat/libp2p-bump-release-v2.0.0

This commit is contained in:
Fabiana Cecin 2026-06-10 11:19:49 -03:00
commit 69e4d959b1
No known key found for this signature in database
GPG Key ID: BCAB8A55CB51B6C7
542 changed files with 3998 additions and 5811 deletions

View File

@ -11,8 +11,8 @@ assignees: ''
### Bumped items
- [ ] Update nimble dependencies
1. Edit manually waku.nimble. For some dependencies, we want to bump versions manually and use a pinned version, f.e., nim-libp2p and all its dependencies.
2. Run `nimble lock` (make sure `nimble --version` shows the Nimble version pinned in waku.nimble)
1. Edit manually logos_delivery.nimble. For some dependencies, we want to bump versions manually and use a pinned version, f.e., nim-libp2p and all its dependencies.
2. Run `nimble lock` (make sure `nimble --version` shows the Nimble version pinned in logos_delivery.nimble)
3. Run `./tools/gen-nix-deps.sh nimble.lock nix/deps.nix` to update nix deps
- [ ] Update vendor/zerokit dependency.

View File

@ -18,7 +18,7 @@ For detailed info on the release process refer to https://github.com/logos-messa
All items below are to be completed by the owner of the given release.
- [ ] Create release branch with major and minor only ( e.g. release/v0.X ) if it doesn't exist.
- [ ] Update the `version` field in `waku.nimble` to match the release version (e.g. `version = "0.X.0"`) **and merge it before assigning any tag** - the `release-assets` workflow gates artifact build/upload.
- [ ] Update the `version` field in `logos_delivery.nimble` to match the release version (e.g. `version = "0.X.0"`) **and merge it before assigning any tag** - the `release-assets` workflow gates artifact build/upload.
- [ ] Assign release candidate tag to the release branch HEAD (e.g. `v0.X.0-rc.0`, `v0.X.0-rc.1`, ... `v0.X.0-rc.N`).
- [ ] Generate and edit release notes in CHANGELOG.md.

View File

@ -34,7 +34,7 @@ jobs:
common:
- '.github/workflows/**'
- 'nimble.lock'
- 'waku.nimble'
- 'logos_delivery.nimble'
- 'Makefile'
- 'scripts/**'
- 'flake.nix'
@ -42,12 +42,11 @@ jobs:
- 'library/**'
- 'liblogosdelivery/**'
v2:
- 'waku/**'
- 'logos_delivery/**'
- 'apps/**'
- 'tools/**'
- 'tests/all_tests_v2.nim'
- 'tests/**'
- 'channels/**'
docker:
- 'docker/**'
@ -89,12 +88,15 @@ jobs:
path: |
nimbledeps/
nimble.paths
key: ${{ runner.os }}-nimbledeps-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
key: ${{ runner.os }}-nimbledeps-v2-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
- name: Install nimble deps
if: steps.cache-nimbledeps.outputs.cache-hit != 'true'
run: |
nimble setup --localdeps -y
# nim's source tree checksums differently across platforms, so its
# locked checksum is unreliable. --useSystemNim uses the CI nim and
# skips that check, while still verifying every other locked dep.
nimble setup --localdeps -y --useSystemNim
make rebuild-nat-libs-nimbledeps
make rebuild-bearssl-nimbledeps
touch nimbledeps/.nimble-setup
@ -142,12 +144,15 @@ jobs:
path: |
nimbledeps/
nimble.paths
key: ${{ runner.os }}-nimbledeps-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
key: ${{ runner.os }}-nimbledeps-v2-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
- name: Install nimble deps
if: steps.cache-nimbledeps.outputs.cache-hit != 'true'
run: |
nimble setup --localdeps -y
# nim's source tree checksums differently across platforms, so its
# locked checksum is unreliable. --useSystemNim uses the CI nim and
# skips that check, while still verifying every other locked dep.
nimble setup --localdeps -y --useSystemNim
make rebuild-nat-libs-nimbledeps
make rebuild-bearssl-nimbledeps
touch nimbledeps/.nimble-setup
@ -207,12 +212,15 @@ jobs:
path: |
nimbledeps/
nimble.paths
key: ${{ runner.os }}-nimbledeps-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
key: ${{ runner.os }}-nimbledeps-v2-nimble${{ env.NIMBLE_VERSION }}-${{ hashFiles('nimble.lock', 'BearSSL.mk', 'Nat.mk') }}
- name: Install nimble deps
if: steps.cache-nimbledeps.outputs.cache-hit != 'true'
run: |
nimble setup --localdeps -y
# nim's source tree checksums differently across platforms, so its
# locked checksum is unreliable. --useSystemNim uses the CI nim and
# skips that check, while still verifying every other locked dep.
nimble setup --localdeps -y --useSystemNim
make rebuild-nat-libs-nimbledeps
make rebuild-bearssl-nimbledeps
touch nimbledeps/.nimble-setup
@ -226,5 +234,5 @@ jobs:
shopt -s extglob # Enable extended globbing
NPH=$(make print-nph-path)
echo "using nph at ${NPH}"
"${NPH}" examples waku tests tools apps *.@(nim|nims|nimble)
"${NPH}" examples logos_delivery tests tools apps *.@(nim|nims|nimble)
git diff --exit-code

View File

@ -15,6 +15,10 @@ env:
NPROC: 2
MAKEFLAGS: "-j${NPROC}"
NIMFLAGS: "--parallelBuild:${NPROC}"
# logos_delivery.nimble reads compile flags from NIM_PARAMS, not NIMFLAGS. Without
# -d:disableMarchNative here, config.nims applies -march=native and
# secp256k1 fails to compile.
NIM_PARAMS: "-d:disableMarchNative"
NIM_VERSION: '2.2.4'
NIMBLE_VERSION: '0.22.3'

View File

@ -26,8 +26,8 @@ jobs:
- 'apps/chat2bridge/config_chat2bridge.nim'
db_schema:
- 'waku/waku_archive/driver/postgres_driver/postgres_driver.nim'
- 'waku/waku_archive/driver/sqlite_driver/queries.nim'
- 'logos_delivery/waku/waku_archive/driver/postgres_driver/postgres_driver.nim'
- 'logos_delivery/waku/waku_archive/driver/sqlite_driver/queries.nim'
- name: Comment config change
uses: thollander/actions-comment-pull-request@v2
if: ${{steps.filter.outputs.config == 'true'}}

View File

@ -11,7 +11,7 @@ env:
NPROC: 2
jobs:
# Release gate: the pushed tag MUST exactly match waku.nimble's version,
# Release gate: the pushed tag MUST exactly match logos_delivery.nimble's version,
# so every published artifact reports the correct getNodeInfo Version.
# CI cannot reject/remove a tag, so we gate artifact build & upload on
# this instead: a mismatched tag yields no released artifacts.
@ -19,24 +19,24 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Assert pushed tag equals waku.nimble version
- name: Assert pushed tag equals logos_delivery.nimble version
if: startsWith(github.ref, 'refs/tags/')
run: |
set -euo pipefail
NIMBLE_VERSION=$(grep -m1 '^version = ' waku.nimble | sed -E 's/version = "([^"]+)"/\1/')
NIMBLE_VERSION=$(grep -m1 '^version = ' logos_delivery.nimble | sed -E 's/version = "([^"]+)"/\1/')
# Strip leading v and any prerelease suffix (e.g. v0.38.0-rc.1 ->
# 0.38.0) so release-candidate tags build against the same
# waku.nimble version as the final tag.
# logos_delivery.nimble version as the final tag.
TAG_VERSION="${GITHUB_REF_NAME#v}"
BASE_VERSION="${TAG_VERSION%%-*}"
echo "tag: ${GITHUB_REF_NAME} (base ${BASE_VERSION})"
echo "waku.nimble version: ${NIMBLE_VERSION}"
echo "logos_delivery.nimble version: ${NIMBLE_VERSION}"
if [ "${BASE_VERSION}" != "${NIMBLE_VERSION}" ]; then
echo "::error::Tag ${GITHUB_REF_NAME} (base ${BASE_VERSION}) does not match"
echo "::error::waku.nimble version (${NIMBLE_VERSION}). Bump waku.nimble before tagging."
echo "::error::logos_delivery.nimble version (${NIMBLE_VERSION}). Bump logos_delivery.nimble before tagging."
exit 1
fi
echo "OK: tag base matches waku.nimble."
echo "OK: tag base matches logos_delivery.nimble."
build-and-upload:
needs: verify-version

View File

@ -7,12 +7,12 @@ on:
branches: [master]
jobs:
# PR check: waku.nimble version must be >= the nearest tag reachable from
# PR check: logos_delivery.nimble version must be >= the nearest tag reachable from
# this branch (`git describe --tags --abbrev=0`, i.e. ancestor-aware).
# Because we check out the PR HEAD (not the simulated merge ref), a branch
# that predates a release tag does not see that tag in its history, so a
# newly pushed tag does NOT break in-flight PRs. Once the branch merges/
# rebases past the tag, the bump is then enforced. This keeps waku.nimble
# rebases past the tag, the bump is then enforced. This keeps logos_delivery.nimble
# fixed as early as possible, independent of whether a release is cut.
# The exact tag==nimble guarantee at release time lives in
# release-assets.yml, which gates artifact publishing on it.
@ -23,10 +23,10 @@ jobs:
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Compare waku.nimble version with nearest ancestor tag
- name: Compare logos_delivery.nimble version with nearest ancestor tag
run: |
set -euo pipefail
NIMBLE_VERSION=$(grep -m1 '^version = ' waku.nimble | sed -E 's/version = "([^"]+)"/\1/')
NIMBLE_VERSION=$(grep -m1 '^version = ' logos_delivery.nimble | sed -E 's/version = "([^"]+)"/\1/')
# Nearest tag reachable from HEAD; --abbrev=0 drops the -<n>-g<sha>
# suffix so we get the bare tag (e.g. v0.38.0). `--match 'v*'` skips
# the moving `nightly` tag (auto-updated by the daily CI to point at
@ -36,7 +36,7 @@ jobs:
BASE_TAG=${BASE_TAG#v}
# Compare on the base version, ignoring any -rc.N prerelease suffix.
BASE_TAG=${BASE_TAG%%-*}
echo "waku.nimble version: ${NIMBLE_VERSION}"
echo "logos_delivery.nimble version: ${NIMBLE_VERSION}"
echo "ancestor git tag: ${BASE_TAG:-<none>}"
if [ -z "${BASE_TAG}" ]; then
echo "No ancestor release tag; skipping."
@ -45,8 +45,8 @@ jobs:
# lowest of the two by version sort must be the tag => nimble >= tag
LOWEST=$(printf '%s\n%s\n' "${NIMBLE_VERSION}" "${BASE_TAG}" | sort -V | head -1)
if [ "${LOWEST}" != "${BASE_TAG}" ] && [ "${NIMBLE_VERSION}" != "${BASE_TAG}" ]; then
echo "::error::waku.nimble version (${NIMBLE_VERSION}) is behind its"
echo "::error::ancestor git tag (v${BASE_TAG}). Bump 'version' in waku.nimble."
echo "::error::logos_delivery.nimble version (${NIMBLE_VERSION}) is behind its"
echo "::error::ancestor git tag (v${BASE_TAG}). Bump 'version' in logos_delivery.nimble."
exit 1
fi
echo "OK: waku.nimble is not behind its ancestor tag."
echo "OK: logos_delivery.nimble is not behind its ancestor tag."

View File

@ -24,6 +24,16 @@ jobs:
MSYSTEM: MINGW64
steps:
- name: Configure Git to keep LF line endings
# Windows Git defaults to core.autocrlf=true. The LF→CRLF conversion
# changes the SHA1 of nimble's cloned deps, so they no longer match
# nimble.lock and nimble re-downloads them on every run (hanging the
# job). Disable autocrlf so clones match the Linux-computed checksums.
shell: pwsh
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout code
uses: actions/checkout@v4
@ -52,6 +62,14 @@ jobs:
mingw-w64-x86_64-clang
mingw-w64-x86_64-nasm
- name: Configure Git in MSYS2 to keep LF line endings
# The step above only configures Git for Windows. nimble clones its deps
# from the MSYS2 shell, whose git reads a separate global config, so the
# same setting must be repeated here.
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Manually install nasm
run: |
bash scripts/install_nasm_in_windows.sh
@ -80,19 +98,16 @@ jobs:
cd /tmp && nimble install "nimble@${{ env.NIMBLE_VERSION }}" -y
echo "$HOME/.nimble/bin" >> $GITHUB_PATH
- name: Patch nimble.lock for Windows nim checksum
# nimble.exe uses Windows Git (core.autocrlf=true by default), which converts LF→CRLF
# on checkout. This changes the SHA1 of the nim package source tree relative to the
# Linux-computed checksum stored in nimble.lock. Patch the lock file with the
# Windows-computed checksum before nimble reads it.
run: |
sed -i 's/68bb85cbfb1832ce4db43943911b046c3af3caab/a092a045d3a427d127a5334a6e59c76faff54686/g' nimble.lock
- name: Install nimble deps
if: steps.cache-nimbledeps.outputs.cache-hit != 'true'
run: |
export PATH="$GITHUB_WORKSPACE/.nim_runtime/bin:$HOME/.nimble/bin:$PATH"
nimble setup --localdeps -y
# nim's source tree checks out differently per platform (its own
# .gitattributes forces line endings), so its locked checksum never
# matches on Windows — even with autocrlf disabled. --useSystemNim
# uses the CI-installed nim and skips that check, while still
# verifying every other locked dependency.
nimble setup --localdeps -y --useSystemNim
make rebuild-nat-libs-nimbledeps CC=gcc
make rebuild-bearssl-nimbledeps CC=gcc
touch nimbledeps/.nimble-setup

1
.gitignore vendored
View File

@ -10,6 +10,7 @@
/tags
# a symlink that can't be added to the repo because of Windows
/logos_delivery.nims
/waku.nims
# Ignore dynamic, static libs and libtool archive files

View File

@ -78,7 +78,7 @@ type WakuFilter* = ref object of LPProtocol
## Development Essentials
### Build Requirements
- Nim 2.x (check `waku.nimble` for minimum version)
- Nim 2.x (check `logos_delivery.nimble` for minimum version)
- Rust toolchain (required for RLN dependencies)
- Build system: Make driven by Nimble (dependencies pinned in `nimble.lock`)
@ -94,7 +94,7 @@ make wakunode2
make wakunode2 NIMFLAGS="-d:chronicles_log_level=DEBUG"
```
Note: The build uses `--mm:refc` memory management (passed automatically by the Nimble tasks in `waku.nimble`). Only relevant if compiling outside the standard build system.
Note: The build uses `--mm:refc` memory management (passed automatically by the Nimble tasks in `logos_delivery.nimble`). Only relevant if compiling outside the standard build system.
### Common Make Targets
```bash
@ -476,7 +476,7 @@ nim c -r \
### Memory Management
- Uses `refc` (reference counting with cycle collection)
- Automatically enforced by the build system (hardcoded in `waku.nimble`)
- Automatically enforced by the build system (hardcoded in `logos_delivery.nimble`)
- Do not override unless absolutely necessary, as it breaks compatibility
### RLN Dependencies
@ -489,7 +489,7 @@ Language: Nim 2.x | License: MIT or Apache 2.0
### Important Files
- `Makefile` - Primary build interface
- `waku.nimble` - Package definition and build tasks (invoked by the Makefile via Nimble)
- `logos_delivery.nimble` - Package definition and build tasks (invoked by the Makefile via Nimble)
- `nimble.lock` - Pinned dependency versions resolved into `nimbledeps/`
- `waku/node/waku_node.nim` - Core node implementation
- `apps/wakunode2/wakunode2.nim` - Main CLI application
@ -511,7 +511,7 @@ Language: Nim 2.x | License: MIT or Apache 2.0
- `presto` - REST server
- `nimcrypto` - Cryptographic primitives
Note: For specific version requirements, check `waku.nimble`.
Note: For specific version requirements, check `logos_delivery.nimble`.
<!-- gitnexus:start -->
# GitNexus — Code Intelligence

View File

@ -24,7 +24,14 @@ export PATH := $(HOME)/.nimble/bin:$(PATH)
# NIM binary location
NIM_BINARY := $(shell which nim 2>/dev/null)
NPH := $(HOME)/.nimble/bin/nph
NIMBLE := $(HOME)/.nimble/bin/nimble
NIMBLE := nimble
ifeq ($(detected_OS),Windows)
# Resolve nimble via PATH (Windows has no $(HOME)/.nimble/bin); --useSystemNim
# reuses the nim on PATH so nimble never re-clones the locked nim.
NIMBLE := nimble --useSystemNim
endif
NIMBLEDEPS_STAMP := nimbledeps/.nimble-setup
# Compilation parameters
@ -68,10 +75,10 @@ endif
%:
@true
waku.nims:
ln -s waku.nimble $@
logos_delivery.nims:
ln -s logos_delivery.nimble $@
$(NIMBLEDEPS_STAMP): nimble.lock | install-nimble build-nph waku.nims
$(NIMBLEDEPS_STAMP): nimble.lock | install-nimble build-nph logos_delivery.nims
$(NIMBLE) setup --localdeps
touch $@
@ -89,8 +96,8 @@ clean:
rm nimble.paths 2> /dev/null || true
nimble clean
REQUIRED_NIM_VERSION := $(shell grep -E '^const RequiredNimVersion\s*=' waku.nimble | grep -oE '"[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"')
REQUIRED_NIMBLE_VERSION := $(shell grep -E '^const RequiredNimbleVersion\s*=' waku.nimble | grep -oE '"[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"')
REQUIRED_NIM_VERSION := $(shell grep -E '^const RequiredNimVersion\s*=' logos_delivery.nimble | grep -oE '"[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"')
REQUIRED_NIMBLE_VERSION := $(shell grep -E '^const RequiredNimbleVersion\s*=' logos_delivery.nimble | grep -oE '"[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"')
install-nim:
ifneq ($(detected_OS),Windows)
@ -207,7 +214,7 @@ clean: | clean-librln
testcommon: | build-deps build
echo -e $(BUILD_MSG) "build/$@" && \
nimble testcommon
$(NIMBLE) testcommon
##########
## Waku ##
@ -216,60 +223,67 @@ testcommon: | build-deps build
testwaku: | build-deps build rln-deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble test
$(NIMBLE) test
# Windows: build with nim directly — `nimble <task>` re-clones git deps every
# build and they intermittently hang on the MSYS2 runner. Flags mirror logos_delivery.nimble.
wakunode2: | build-deps build deps librln
ifeq ($(detected_OS),Windows)
echo -e $(BUILD_MSG) "build/$@" && \
nimble wakunode2
nim c --out:build/wakunode2 --mm:refc --cpu:amd64 $(NIM_PARAMS) -d:chronicles_log_level=TRACE apps/wakunode2/wakunode2.nim
else
echo -e $(BUILD_MSG) "build/$@" && \
$(NIMBLE) wakunode2
endif
benchmarks: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble benchmarks
$(NIMBLE) benchmarks
testwakunode2: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble testwakunode2
$(NIMBLE) testwakunode2
example2: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble example2
$(NIMBLE) example2
chat2: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble chat2
$(NIMBLE) chat2
chat2mix: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble chat2mix
$(NIMBLE) chat2mix
rln-db-inspector: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble rln_db_inspector
$(NIMBLE) rln_db_inspector
chat2bridge: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble chat2bridge
$(NIMBLE) chat2bridge
liteprotocoltester: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble liteprotocoltester
$(NIMBLE) liteprotocoltester
lightpushwithmix: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble lightpushwithmix
$(NIMBLE) lightpushwithmix
api_example: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim api_example $(NIM_PARAMS) waku.nims
$(ENV_SCRIPT) nim api_example $(NIM_PARAMS) logos_delivery.nims
build/%: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$*" && \
nimble buildone $*
$(NIMBLE) buildone $*
compile-test: | build-deps build deps librln
echo -e $(BUILD_MSG) "$(TEST_FILE)" "\"$(TEST_NAME)\"" && \
nimble buildTest $(TEST_FILE) && \
nimble execTest $(TEST_FILE) "\"$(TEST_NAME)\""
$(NIMBLE) buildTest $(TEST_FILE) && \
$(NIMBLE) execTest $(TEST_FILE) "\"$(TEST_NAME)\""
################
## Waku tools ##
@ -280,11 +294,11 @@ tools: networkmonitor wakucanary
wakucanary: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble wakucanary
$(NIMBLE) wakucanary
networkmonitor: | build-deps build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble networkmonitor
$(NIMBLE) networkmonitor
############
## Format ##
@ -330,7 +344,7 @@ clean:
docs: | build deps
echo -e $(BUILD_MSG) "build/$@" && \
nimble doc --run --index:on --project --out:.gh-pages waku/waku.nim waku.nims
$(NIMBLE) doc --run --index:on --project --out:.gh-pages logos-delivery/logos-delivery.nim logos_delivery.nims
coverage:
echo -e $(BUILD_MSG) "build/$@" && \
@ -426,11 +440,16 @@ else ifeq ($(detected_OS),Linux)
BUILD_COMMAND := $(BUILD_COMMAND)Linux
endif
# Windows: build with nim directly (see wakunode2). Flags mirror logos_delivery.nimble.
libwaku: | build-deps librln
nimble --verbose libwaku$(BUILD_COMMAND) waku.nimble
ifeq ($(detected_OS),Windows)
nim c --out:build/libwaku.dll --threads:on --app:lib --opt:speed --noMain --mm:refc --header -d:metrics --nimMainPrefix:libwaku --skipParentCfg:off -d:discv5_protocol_id=d5waku --cpu:amd64 $(NIM_PARAMS) library/libwaku.nim
else
$(NIMBLE) --verbose libwaku$(BUILD_COMMAND) logos_delivery.nimble
endif
liblogosdelivery: | build-deps librln
nimble --verbose liblogosdelivery$(BUILD_COMMAND) waku.nimble
$(NIMBLE) --verbose liblogosdelivery$(BUILD_COMMAND) logos_delivery.nimble
logosdelivery_example: | build liblogosdelivery
@echo -e $(BUILD_MSG) "build/$@"
@ -505,7 +524,7 @@ endif
build-libwaku-for-android-arch:
ifneq ($(findstring /nix/store,$(LIBRLN_FILE)),)
mkdir -p $(CURDIR)/build/android/$(ABIDIR)/
CPU=$(CPU) ABIDIR=$(ABIDIR) ANDROID_ARCH=$(ANDROID_ARCH) ANDROID_COMPILER=$(ANDROID_COMPILER) ANDROID_TOOLCHAIN_DIR=$(ANDROID_TOOLCHAIN_DIR) nimble libWakuAndroid
CPU=$(CPU) ABIDIR=$(ABIDIR) ANDROID_ARCH=$(ANDROID_ARCH) ANDROID_COMPILER=$(ANDROID_COMPILER) ANDROID_TOOLCHAIN_DIR=$(ANDROID_TOOLCHAIN_DIR) $(NIMBLE) libWakuAndroid
else
./scripts/build_rln_android.sh $(CURDIR)/build $(LIBRLN_BUILDDIR) $(LIBRLN_VERSION) $(CROSS_TARGET) $(ABIDIR)
endif
@ -562,7 +581,7 @@ else
endif
build-libwaku-for-ios-arch:
IOS_SDK=$(IOS_SDK) IOS_ARCH=$(IOS_ARCH) IOS_SDK_PATH=$(IOS_SDK_PATH) nimble libWakuIOS
IOS_SDK=$(IOS_SDK) IOS_ARCH=$(IOS_ARCH) IOS_SDK_PATH=$(IOS_SDK_PATH) $(NIMBLE) libWakuIOS
libwaku-ios-device: IOS_ARCH=arm64
libwaku-ios-device: IOS_SDK=iphoneos
@ -592,4 +611,4 @@ release-notes:
-u $(shell id -u) \
docker.io/wakuorg/sv4git:latest \
release-notes |\
sed -E 's@#([0-9]+)@[#\1](https://github.com/waku-org/nwaku/issues/\1)@g'
sed -E 's@#([0-9]+)@[#\1](https://github.com/logos-messaging/logos-delivery/issues/\1)@g'

View File

@ -2,7 +2,7 @@ import
std/[strutils, times, sequtils, osproc], math, results, options, testutils/unittests
import
waku/[
logos_delivery/waku/[
waku_rln_relay/protocol_types,
waku_rln_relay/rln,
waku_rln_relay,

View File

@ -31,7 +31,7 @@ import
nameresolving/dnsresolver,
] # define DNS resolution
import
waku/[
logos_delivery/waku/[
waku_core,
waku_lightpush_legacy/common,
waku_lightpush_legacy/rpc,
@ -48,7 +48,7 @@ import
./config_chat2
import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub
import ../../waku/waku_rln_relay
import ../../logos_delivery/waku/waku_rln_relay
const Help = """
Commands: /[?|help|connect|nick|exit]

View File

@ -10,7 +10,7 @@ import
nimcrypto/utils,
std/strutils,
regex
import waku/waku_core
import logos_delivery/waku/waku_core
type
Fleet* = enum

View File

@ -15,7 +15,7 @@ import
# Waku v2 imports
libp2p/crypto/crypto,
libp2p/errors,
waku/[
logos_delivery/waku/[
waku_core,
waku_node,
node/peer_manager,
@ -242,7 +242,8 @@ proc stop*(cmb: Chat2MatterBridge) {.async: (raises: [Exception]).} =
{.pop.}
# @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError
when isMainModule:
import waku/common/utils/nat, waku/rest_api/message_cache
import
logos_delivery/waku/common/utils/nat, logos_delivery/waku/rest_api/message_cache
let
rng = newRng()

View File

@ -33,7 +33,7 @@ import
protocols/mix/mix_protocol,
] # define DNS resolution
import
waku/[
logos_delivery/waku/[
waku_core,
waku_lightpush/common,
waku_lightpush/rpc,
@ -52,7 +52,7 @@ import
./config_chat2mix
import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub
import ../../waku/waku_rln_relay
import ../../logos_delivery/waku/waku_rln_relay
logScope:
topics = "chat2 mix"

View File

@ -12,7 +12,7 @@ import
confutils/defs,
confutils/std/net
import waku/waku_core, waku/waku_mix
import logos_delivery/waku/waku_core, logos_delivery/waku/waku_mix
type
Fleet* = enum

View File

@ -8,14 +8,13 @@ import
chronicles,
chronos,
metrics,
libbacktrace,
libp2p/crypto/crypto,
confutils,
libp2p/wire
import
tools/confutils/cli_args,
waku/[
logos_delivery/waku/[
node/peer_manager,
waku_lightpush/common,
waku_relay,

View File

@ -1,5 +1,5 @@
import chronos, results, options
import waku/[waku_node, waku_core]
import logos_delivery/waku/[waku_node, waku_core]
import publisher_base
type LegacyPublisher* = ref object of PublisherBase

View File

@ -5,14 +5,13 @@ import
chronicles,
chronos,
metrics,
libbacktrace,
system/ansi_c,
libp2p/crypto/crypto,
confutils
import
tools/confutils/cli_args,
waku/[
logos_delivery/waku/[
common/enr,
common/logging,
factory/waku as waku_factory,
@ -96,7 +95,7 @@ when isMainModule:
wakuNodeConf.shards = @[conf.shard]
wakuNodeConf.contentTopics = conf.contentTopics
wakuNodeConf.clusterId = conf.clusterId
wakuNodeConf.clusterId = some(conf.clusterId)
## TODO: Depending on the tester needs we might extend here with shards, clusterId, etc...
wakuNodeConf.metricsServer = true
@ -123,7 +122,7 @@ when isMainModule:
error "Waku initialization failed", error = error
quit(QuitFailure)
(waitFor startWaku(addr waku)).isOkOr:
(waitFor waku.start()).isOkOr:
error "Starting waku failed", error = error
quit(QuitFailure)
@ -156,7 +155,7 @@ when isMainModule:
when defined(posix):
proc handleSigsegv(signal: cint) {.noconv.} =
# Require --debugger:native
fatal "Shutting down after receiving SIGSEGV", stacktrace = getBacktrace()
fatal "Shutting down after receiving SIGSEGV"
# Not available in -d:release mode
writeStackTrace()

View File

@ -8,7 +8,7 @@ import
results,
json_serialization as js
import
waku/[
logos_delivery/waku/[
common/logging,
waku_node,
node/peer_manager,

View File

@ -1,5 +1,5 @@
import chronos, results
import waku/[waku_node, waku_core]
import logos_delivery/waku/[waku_node, waku_core]
type PublisherBase* = ref object of RootObj
wakuNode*: WakuNode

View File

@ -13,7 +13,7 @@ import
json_serialization as js
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_node,

View File

@ -5,14 +5,13 @@ import
chronicles,
chronos,
metrics,
libbacktrace,
libp2p/crypto/crypto,
confutils,
libp2p/wire
import
tools/confutils/cli_args,
waku/[
logos_delivery/waku/[
common/enr,
waku_node,
node/peer_manager,

View File

@ -14,7 +14,7 @@ import
import
../../tools/confutils/
[cli_args, envvar as confEnvvarDefs, envvar_net as confEnvvarNet],
waku/[common/logging, waku_core, waku_core/topics/pubsub_topic]
logos_delivery/waku/[common/logging, waku_core, waku_core/topics/pubsub_topic]
export confTomlDefs, confTomlNet, confEnvvarDefs, confEnvvarNet

View File

@ -6,7 +6,7 @@ import
json_serialization/std/options,
json_serialization/lexer
import waku/rest_api/endpoint/serdes
import logos_delivery/waku/rest_api/endpoint/serdes
type ProtocolTesterMessage* = object
sender*: string

View File

@ -1,5 +1,5 @@
import results, options, chronos
import waku/[waku_node, waku_core, waku_lightpush, waku_lightpush/common]
import logos_delivery/waku/[waku_node, waku_core, waku_lightpush, waku_lightpush/common]
import publisher_base
type V3Publisher* = ref object of PublisherBase

View File

@ -17,7 +17,7 @@ import
metrics/chronos_httpserver,
presto/[route, server, client]
import
waku/[
logos_delivery/waku/[
waku_core,
node/peer_manager,
waku_node,
@ -550,7 +550,7 @@ when isMainModule:
info "cli flags", conf = conf
if conf.clusterId == 1:
let twnNetworkConf = NetworkConf.TheWakuNetworkConf()
let twnNetworkConf = NetworkPresetConf.TheWakuNetworkConf()
conf.bootstrapNodes = twnNetworkConf.discv5BootstrapNodes
conf.rlnRelayDynamic = twnNetworkConf.rlnRelayDynamic

View File

@ -12,9 +12,11 @@ import
libp2p/multicodec
import
./certsgenerator,
waku/[waku_enr, node/peer_manager, waku_core, waku_node, factory/builder],
waku/waku_metadata/protocol,
waku/common/callbacks
logos_delivery/waku/
[waku_enr, node/peer_manager, waku_core, waku_node, factory/builder],
logos_delivery/waku/net/net_config,
logos_delivery/waku/waku_metadata/protocol,
logos_delivery/waku/common/callbacks
# protocols and their tag
const ProtocolsTable = {

View File

@ -9,7 +9,7 @@ import
libp2p/crypto/crypto
import
../../tools/[rln_keystore_generator/rln_keystore_generator, confutils/cli_args],
waku/[
logos_delivery/waku/[
common/logging,
factory/waku,
node/health_monitor,
@ -55,7 +55,7 @@ when isMainModule:
error "Waku initialization failed", error = error
quit(QuitFailure)
(waitFor startWaku(addr waku)).isOkOr:
(waitFor waku.start()).isOkOr:
error "Starting waku failed", error = error
quit(QuitFailure)

View File

@ -124,13 +124,13 @@ def versionWasChanged(version) {
script: "git diff --name-only origin/${env.CHANGE_TARGET}",
returnStdout: true
)
if (changes =~ "(?m)^(Makefile|waku.nimble|config.nims|vendor|ci|shell.nix).*") {
if (changes =~ "(?m)^(Makefile|logos_delivery.nimble|config.nims|vendor|ci|shell.nix).*") {
return true
}
if (version == 'v2' && changes =~ "(?m)^(apps|tools)/.*") {
return true
}
if (changes =~ "(?m)^(waku|tests|examples)/(${version}|common)/.*") {
if (changes =~ "(?m)^(logos_delivery|tests|examples)/(${version}|common)/.*") {
return true
}
return false

View File

@ -1,6 +1,6 @@
import std/options
import chronos, results, confutils, confutils/defs
import waku
import logos_delivery
type CliArgs = object
ethRpcEndpoint* {.
@ -82,8 +82,12 @@ when isMainModule:
echo("Waku node created successfully!")
node.mountMessagingClient().isOkOr:
echo "Failed to mount messaging: ", error
quit(QuitFailure)
# Start the node
(waitFor startWaku(addr node)).isOkOr:
(waitFor node.start()).isOkOr:
echo "Failed to start node: ", error
quit(QuitFailure)

View File

@ -9,7 +9,7 @@ import
eth/p2p/discoveryv5/enr
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_core,

View File

@ -16,7 +16,7 @@ import
metrics/chronos_httpserver
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_core,

View File

@ -5,7 +5,7 @@ import
libp2p/multicodec,
nimcrypto/utils as ncrutils
import waku/waku_mix
import logos_delivery/waku/waku_mix
type LightPushMixConf* = object
destPeerAddr* {.desc: "Destination peer address with peerId.", name: "dp-addr".}:

View File

@ -10,7 +10,7 @@ import
eth/p2p/discoveryv5/enr
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_core,

View File

@ -9,7 +9,7 @@ import
eth/p2p/discoveryv5/enr
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_core,

View File

@ -9,7 +9,7 @@ import
eth/p2p/discoveryv5/enr
import
waku/[
logos_delivery/waku/[
common/logging,
node/peer_manager,
waku_core,

View File

@ -1,18 +1,17 @@
{.push raises: [].}
import tools/confutils/cli_args
import waku/[common/logging, factory/[waku, networks_config]]
import logos_delivery/waku/[common/logging, factory/[waku, networks_config]]
import
std/[options, strutils, os, sequtils],
chronicles,
chronos,
metrics,
libbacktrace,
libp2p/crypto/crypto
export
networks_config, waku, logging, options, strutils, os, sequtils, stewNet, chronicles,
chronos, metrics, libbacktrace, crypto
chronos, metrics, crypto
proc setup*(): Waku =
const versionString = "version / git commit hash: " & waku.git_version
@ -22,7 +21,7 @@ proc setup*(): Waku =
error "failure while loading the configuration", error = $error
quit(QuitFailure)
let twnNetworkConf = NetworkConf.TheWakuNetworkConf()
let twnNetworkConf = NetworkPresetConf.TheWakuNetworkConf()
if len(conf.shards) != 0:
conf.pubsubTopics = conf.shards.mapIt(twnNetworkConf.pubsubTopics[it.uint16])
else:
@ -30,25 +29,25 @@ proc setup*(): Waku =
# Override configuration
conf.maxMessageSize = twnNetworkConf.maxMessageSize
conf.clusterId = twnNetworkConf.clusterId
conf.clusterId = some(twnNetworkConf.clusterId)
conf.rlnRelayEthContractAddress = twnNetworkConf.rlnRelayEthContractAddress
conf.rlnRelayDynamic = twnNetworkConf.rlnRelayDynamic
conf.discv5Discovery = twnNetworkConf.discv5Discovery
conf.rlnRelayDynamic = some(twnNetworkConf.rlnRelayDynamic)
conf.discv5Discovery = some(twnNetworkConf.discv5Discovery)
conf.discv5BootstrapNodes =
conf.discv5BootstrapNodes & twnNetworkConf.discv5BootstrapNodes
conf.rlnEpochSizeSec = twnNetworkConf.rlnEpochSizeSec
conf.rlnRelayUserMessageLimit = twnNetworkConf.rlnRelayUserMessageLimit
conf.rlnEpochSizeSec = some(twnNetworkConf.rlnEpochSizeSec)
conf.rlnRelayUserMessageLimit = some(twnNetworkConf.rlnRelayUserMessageLimit)
# Only set rlnRelay to true if relay is configured
if conf.relay:
conf.rlnRelay = twnNetworkConf.rlnRelay
conf.rlnRelay = some(twnNetworkConf.rlnRelay)
info "Starting node"
var waku = (waitFor Waku.new(conf)).valueOr:
error "Waku initialization failed", error = error
quit(QuitFailure)
(waitFor startWaku(addr waku)).isOkOr:
(waitFor waku.start()).isOkOr:
error "Starting waku failed", error = error
quit(QuitFailure)

View File

@ -2,7 +2,7 @@
import
results,
waku/[common/logging, waku_node, waku_rln_relay],
logos_delivery/waku/[common/logging, waku_node, waku_rln_relay],
./erc_5564_interface as StealthCommitmentFFI,
./node_spec,
./wire_spec

View File

@ -1,7 +1,7 @@
import std/[times, options]
import confutils, chronicles, chronos, results
import waku/[waku_core, common/protobuf]
import logos_delivery/waku/[waku_core, common/protobuf]
import libp2p/protobuf/minprotobuf
export

54
flake.lock generated
View File

@ -2,24 +2,25 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1770464364,
"narHash": "sha256-z5NJPSBwsLf/OfD8WTmh79tlSU8XgIbwmk6qB1/TFzY=",
"lastModified": 1780511130,
"narHash": "sha256-2v9lT4ya59Lh1FqPeLnz1MoX9y/wz2huqfe9RtQZITk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "23d72dabcb3b12469f57b37170fcbc1789bd7457",
"rev": "535f3e6942cb1cead3929c604320d3db54b542b9",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "23d72dabcb3b12469f57b37170fcbc1789bd7457",
"rev": "535f3e6942cb1cead3929c604320d3db54b542b9",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
"rust-overlay": "rust-overlay",
"zerokit": "zerokit"
}
},
"rust-overlay": {
@ -41,6 +42,49 @@
"repo": "rust-overlay",
"type": "github"
}
},
"rust-overlay_2": {
"inputs": {
"nixpkgs": [
"zerokit",
"nixpkgs"
]
},
"locked": {
"lastModified": 1771297684,
"narHash": "sha256-wieWskQxZLPlNXX06JEB0bMoS/ZYQ89xBzF0RL9lyLs=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "755d3669699a7c62aef35af187d75dc2728cfd85",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"zerokit": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1779168423,
"narHash": "sha256-OmCnpM+ZcI79EVozdKADj9h4sFsLwfCs5w7OK8Ir6fc=",
"owner": "vacp2p",
"repo": "zerokit",
"rev": "5e64cb8822bee65eed6cf459f95ae72b80c6ba63",
"type": "github"
},
"original": {
"owner": "vacp2p",
"repo": "zerokit",
"rev": "5e64cb8822bee65eed6cf459f95ae72b80c6ba63",
"type": "github"
}
}
},
"root": "root",

View File

@ -11,15 +11,22 @@
inputs = {
# Pinning the commit to use same commit across different projects.
# A commit from nixpkgs 25.11 release: https://github.com/NixOS/nixpkgs/tree/release-25.11
nixpkgs.url = "github:NixOS/nixpkgs?rev=23d72dabcb3b12469f57b37170fcbc1789bd7457";
# Includes the fetchCargoVendor crates.io CDN fix (nixpkgs 0fb82de3).
nixpkgs.url = "github:NixOS/nixpkgs?rev=535f3e6942cb1cead3929c604320d3db54b542b9";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
# Zerokit v2.0.2; keep rev in sync with the vendor/zerokit submodule.
zerokit = {
url = "github:vacp2p/zerokit/5e64cb8822bee65eed6cf459f95ae72b80c6ba63";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, rust-overlay }:
outputs = { self, nixpkgs, rust-overlay, zerokit }:
let
systems = [
"x86_64-linux" "aarch64-linux"
@ -32,11 +39,11 @@
lib = nixpkgs.lib;
# Single source of truth for the semver: the `version` field of
# waku.nimble. Kept in sync with git tags by the version-check CI.
# logos_delivery.nimble. Kept in sync with git tags by the version-check CI.
nimbleVersion =
let line = lib.findFirst (l: lib.hasPrefix "version = " l)
"version = \"unknown\""
(lib.splitString "\n" (builtins.readFile ./waku.nimble));
(lib.splitString "\n" (builtins.readFile ./logos_delivery.nimble));
in lib.removeSuffix "\"" (lib.removePrefix "version = \"" line);
# A flake sandbox has no .git, so `git describe` is impossible; the
@ -59,78 +66,12 @@
inherit system;
overlays = [ (import rust-overlay) nimbleOverlay ];
};
# Prebuilt zerokit librln, fetched from the upstream GitHub release
# rather than compiled from source. Compiling zerokit makes Nix download
# its many crate dependencies from crates.io in one parallel burst, which
# crates.io intermittently rejects with HTTP 403 (rate limiting from the
# self-hosted runners' shared IP), breaking the nix build. The release
# ships the exact `stateless` library this project links (see
# scripts/build_rln.sh), so we use it directly — no Rust toolchain and
# no crates.io access needed.
#
# Keep `rlnVersion` aligned with `LIBRLN_VERSION` in the Makefile and the
# vendor/zerokit submodule. Each hash is the sha256 of the release tarball
# for that platform; refresh all four when bumping the version.
rlnVersion = "v2.0.2";
rlnAssets = {
"x86_64-linux" = { triple = "x86_64-unknown-linux-gnu"; hash = "sha256-qbrUdaetYKFhjzxUP/QcwD3JHWJ8qk/tCMK3yXceIAk="; };
"aarch64-linux" = { triple = "aarch64-unknown-linux-gnu"; hash = "sha256-s4bWrmCcNTWHNyJwV73ilWNp58ZdAVG+TAgtWN1cTQs="; };
"x86_64-darwin" = { triple = "x86_64-apple-darwin"; hash = "sha256-ZaHP5CApN66FYY7jxwOmGcF9kJR78Fng3k1qE2W08Mk="; };
"aarch64-darwin" = { triple = "aarch64-apple-darwin"; hash = "sha256-f2YppkPsKFdN00j+IY8fpvsebWTIb9lW/V1/vOTiVKU="; };
};
mkZerokitRln = system: pkgs:
let
asset = rlnAssets.${system} or
(throw "zerokit ${rlnVersion} has no prebuilt rln asset for system '${system}'");
in pkgs.stdenv.mkDerivation {
pname = "librln";
version = lib.removePrefix "v" rlnVersion;
src = pkgs.fetchurl {
url = "https://github.com/vacp2p/zerokit/releases/download/"
+ "${rlnVersion}/${asset.triple}-stateless-rln.tar.gz";
hash = asset.hash;
};
# The tarball lays its files out under release/.
sourceRoot = "release";
dontConfigure = true;
dontBuild = true;
# The release .so was linked outside Nix, so it references system
# libraries (libgcc_s, libstdc++, glibc) by bare name. autoPatchelfHook
# points those at the Nix versions so the library loads correctly when
# used by the Nix build. It does nothing for the static .a, and the
# step is skipped on macOS (dylib paths are fixed in nix/default.nix).
nativeBuildInputs =
pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ];
buildInputs =
pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ];
installPhase = ''
runHook preInstall
mkdir -p $out/lib
cp librln.a $out/lib/ 2>/dev/null || true
cp librln.so $out/lib/ 2>/dev/null || true
cp librln.dylib $out/lib/ 2>/dev/null || true
runHook postInstall
'';
meta = with pkgs.lib; {
description = "Prebuilt zerokit RLN library (stateless flavor)";
homepage = "https://github.com/vacp2p/zerokit";
license = with licenses; [ mit asl20 ];
platforms = builtins.attrNames rlnAssets;
};
};
in {
packages = forAllSystems (system:
let
pkgs = pkgsFor system;
zerokitRln = mkZerokitRln system pkgs;
zerokitRln = import ./nix/zerokit.nix { inherit zerokit system; };
liblogosdelivery = pkgs.callPackage ./nix/default.nix {
inherit pkgs;
@ -147,9 +88,7 @@
};
in {
inherit liblogosdelivery wakucanary;
# Expose the prebuilt librln so downstream consumers
# (e.g. logos-delivery-module) bundle the exact same librln this
# build links against.
# Expose librln so downstream consumers link the exact same build.
rln = zerokitRln;
default = liblogosdelivery;
}

View File

@ -1,6 +1,6 @@
import ffi
import std/locks
import waku/factory/waku
import logos_delivery/waku/factory/waku
declareLibrary("logosdelivery")

View File

@ -1,6 +1,7 @@
import std/[atomics, options]
import chronicles, chronos, chronos/threadsync, ffi
import waku/factory/waku, waku/node/waku_node, ./declare_lib
import
logos_delivery/waku/factory/waku, logos_delivery/waku/node/waku_node, ./declare_lib
################################################################################
## Include different APIs, i.e. all procs with {.ffi.} pragma

View File

@ -1,5 +1,5 @@
import std/[json, strutils]
import waku/factory/waku_state_info
import logos_delivery/waku/factory/waku_state_info
import tools/confutils/[cli_args, config_option_meta]
proc logosdelivery_get_available_node_info_ids(

View File

@ -2,10 +2,10 @@ import std/[json]
import chronos, results, ffi
import stew/byteutils
import
waku/common/base64,
waku/factory/waku,
waku/waku_core/topics/content_topic,
waku/api/[api, types],
logos_delivery/waku/common/base64,
logos_delivery/waku/factory/waku,
logos_delivery/waku/waku_core/topics/content_topic,
logos_delivery/waku/api/[api, types],
../declare_lib
proc logosdelivery_subscribe(

View File

@ -1,11 +1,11 @@
import std/[json, strutils, tables]
import chronos, chronicles, results, confutils, confutils/std/net, ffi
import std/json
import chronos, chronicles, results, ffi
import
waku/factory/waku,
waku/node/waku_node,
waku/api/[api, types],
waku/events/[message_events, health_events],
tools/confutils/cli_args,
logos_delivery/waku/factory/waku,
logos_delivery/waku/node/waku_node,
logos_delivery/waku/api/[api, types],
logos_delivery/waku/events/[message_events, health_events],
tools/confutils/conf_from_json,
../declare_lib,
../json_event
@ -15,59 +15,11 @@ proc `%`*(id: RequestId): JsonNode =
registerReqFFI(CreateNodeRequest, ctx: ptr FFIContext[Waku]):
proc(configJson: cstring): Future[Result[string, string]] {.async.} =
## Parse the JSON configuration using fieldPairs approach (WakuNodeConf)
var conf = defaultWakuNodeConf().valueOr:
return err("Failed creating default conf: " & error)
let conf = parseNodeConfFromJson($configJson).valueOr:
error "Failed to assemble WakuNodeConf from JSON",
error = error, configJson = $configJson
return err("failed parseNodeConfFromJson " & error)
var jsonNode: JsonNode
try:
jsonNode = parseJson($configJson)
except Exception:
let exceptionMsg = getCurrentExceptionMsg()
error "Failed to parse config JSON",
error = exceptionMsg, configJson = $configJson
return err(
"Failed to parse config JSON: " & exceptionMsg & " configJson string: " &
$configJson
)
var jsonFields: Table[string, (string, JsonNode)]
for key, value in jsonNode:
let lowerKey = key.toLowerAscii()
if jsonFields.hasKey(lowerKey):
error "Duplicate configuration option found when normalized to lowercase",
key = key
return err(
"Duplicate configuration option found when normalized to lowercase: '" & key &
"'"
)
jsonFields[lowerKey] = (key, value)
for confField, confValue in fieldPairs(conf):
let lowerField = confField.toLowerAscii()
if jsonFields.hasKey(lowerField):
let (jsonKey, jsonValue) = jsonFields[lowerField]
let formattedString = ($jsonValue).strip(chars = {'\"'})
try:
confValue = parseCmdArg(typeof(confValue), formattedString)
except Exception:
return err(
"Failed to parse field '" & confField & "' from JSON key '" & jsonKey & "': " &
getCurrentExceptionMsg() & ". Value: " & formattedString
)
jsonFields.del(lowerField)
if jsonFields.len > 0:
var unknownKeys = newSeq[string]()
for _, (jsonKey, _) in pairs(jsonFields):
unknownKeys.add(jsonKey)
error "Unrecognized configuration option(s) found", option = unknownKeys
return err("Unrecognized configuration option(s) found: " & $unknownKeys)
# Create the node
ctx.myLib[] = (await api.createNode(conf)).valueOr:
let errMsg = $error
chronicles.error "CreateNodeRequest failed", err = errMsg
@ -96,7 +48,7 @@ proc logosdelivery_create_node(
): pointer {.dynlib, exportc, cdecl.} =
initializeLibrary()
if isNil(callback):
if callback.isNil():
echo "error: missing callback in logosdelivery_create_node"
return nil
@ -172,7 +124,17 @@ proc logosdelivery_start_node(
chronicles.error "ConnectionStatusChange.listen failed", err = $error
return err("ConnectionStatusChange.listen failed: " & $error)
(await startWaku(addr ctx.myLib[])).isOkOr:
ctx.myLib[].mountMessagingClient().isOkOr:
let errMsg = $error
chronicles.error "mountMessagingClient failed", error = errMsg
return err("failed to mount messaging: " & errMsg)
ctx.myLib[].mountReliableChannelManager().isOkOr:
let errMsg = $error
chronicles.error "mountReliableChannelManager failed", err = errMsg
return err("failed to mount reliable channel manager: " & errMsg)
(await ctx.myLib[].start()).isOkOr:
let errMsg = $error
chronicles.error "START_NODE failed", err = errMsg
return err("failed to start: " & errMsg)

View File

@ -1,5 +1,5 @@
import ffi
import waku/factory/waku
import logos_delivery/waku/factory/waku
declareLibrary("waku")

View File

@ -1,6 +1,6 @@
import system, std/json, libp2p/[connmanager, peerid]
import ../../waku/common/base64, ./json_base_event
import ../../logos_delivery/waku/common/base64, ./json_base_event
type JsonConnectionChangeEvent* = ref object of JsonEvent
peerId*: string

View File

@ -2,7 +2,7 @@
import system, std/json
import ./json_base_event
import ../../waku/api/types
import ../../logos_delivery/waku/api/types
type JsonConnectionStatusChangeEvent* = ref object of JsonEvent
status*: ConnectionStatus

View File

@ -1,9 +1,9 @@
import system, results, std/json, std/strutils
import stew/byteutils
import
../../waku/common/base64,
../../waku/waku_core/message,
../../waku/waku_core/message/message,
../../logos_delivery/waku/common/base64,
../../logos_delivery/waku/waku_core/message,
../../logos_delivery/waku/waku_core/message/message,
../utils,
./json_base_event

View File

@ -1,7 +1,7 @@
import system, results, std/json
import stew/byteutils
import ../../waku/common/base64, ./json_base_event
import ../../waku/waku_relay
import ../../logos_delivery/waku/common/base64, ./json_base_event
import ../../logos_delivery/waku/waku_relay
type JsonTopicHealthChangeEvent* = ref object of JsonEvent
pubsubTopic*: string

View File

@ -9,7 +9,10 @@ import
metrics,
ffi
import
waku/factory/waku, waku/node/waku_node, waku/node/health_monitor, library/declare_lib
logos_delivery/waku/factory/waku,
logos_delivery/waku/node/waku_node,
logos_delivery/waku/node/health_monitor,
library/declare_lib
proc getMultiaddresses(node: WakuNode): seq[string] =
return node.info().listenAddresses

View File

@ -1,13 +1,12 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/json
import chronos, chronicles, results, strutils, libp2p/multiaddress, ffi
import
waku/factory/waku,
waku/discovery/waku_dnsdisc,
waku/discovery/waku_discv5,
waku/waku_core/peers,
waku/node/waku_node,
waku/node/kernel_api,
logos_delivery/waku/factory/waku,
logos_delivery/waku/discovery/waku_dnsdisc,
logos_delivery/waku/discovery/waku_discv5,
logos_delivery/waku/waku_core/peers,
logos_delivery/waku/waku_node,
library/declare_lib
proc retrieveBootstrapNodes(

View File

@ -1,14 +1,14 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[options, json, strutils, net]
import chronos, chronicles, results, confutils, confutils/std/net, ffi
import
waku/node/peer_manager/peer_manager,
logos_delivery/waku/node/peer_manager/peer_manager,
tools/confutils/cli_args,
waku/factory/waku,
waku/factory/node_factory,
waku/factory/app_callbacks,
waku/rest_api/endpoint/builder,
logos_delivery/waku/factory/waku,
logos_delivery/waku/factory/node_factory,
logos_delivery/waku/factory/app_callbacks,
logos_delivery/waku/rest_api/endpoint/builder,
library/declare_lib
proc createWaku(
@ -72,7 +72,7 @@ registerReqFFI(CreateNodeRequest, ctx: ptr FFIContext[Waku]):
proc waku_start(
ctx: ptr FFIContext[Waku], callback: FFICallBack, userData: pointer
) {.ffi.} =
(await startWaku(ctx[].myLib)).isOkOr:
(await ctx.myLib[].start()).isOkOr:
error "START_NODE failed", error = error
return err("failed to start: " & $error)
return ok("")

View File

@ -1,7 +1,11 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[sequtils, strutils, tables]
import chronicles, chronos, results, options, json, ffi
import waku/factory/waku, waku/node/waku_node, waku/node/peer_manager, ../declare_lib
import
logos_delivery/waku/factory/waku,
logos_delivery/waku/node/waku_node,
logos_delivery/waku/node/peer_manager,
../declare_lib
type PeerInfo = object
protocols: seq[string]

View File

@ -1,7 +1,9 @@
import std/[json, strutils]
import chronos, results, ffi
import libp2p/[protocols/ping, switch, multiaddress, multicodec]
import waku/[factory/waku, waku_core/peers, node/waku_node], library/declare_lib
import
logos_delivery/waku/[factory/waku, waku_core/peers, node/waku_node],
library/declare_lib
proc waku_ping_peer(
ctx: ptr FFIContext[Waku],

View File

@ -1,18 +1,17 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import options, std/[strutils, sequtils]
import chronicles, chronos, results, ffi
import
waku/waku_filter_v2/client,
waku/waku_core/message/message,
waku/factory/waku,
waku/waku_relay,
waku/waku_filter_v2/common,
waku/waku_core/subscription/push_handler,
waku/node/peer_manager/peer_manager,
waku/node/waku_node,
waku/node/kernel_api,
waku/waku_core/topics/pubsub_topic,
waku/waku_core/topics/content_topic,
logos_delivery/waku/waku_filter_v2/client,
logos_delivery/waku/waku_core/message/message,
logos_delivery/waku/factory/waku,
logos_delivery/waku/waku_relay,
logos_delivery/waku/waku_filter_v2/common,
logos_delivery/waku/waku_core/subscription/push_handler,
logos_delivery/waku/node/peer_manager/peer_manager,
logos_delivery/waku/waku_node,
logos_delivery/waku/waku_core/topics/pubsub_topic,
logos_delivery/waku/waku_core/topics/content_topic,
library/events/json_message_event,
library/declare_lib

View File

@ -1,14 +1,14 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import options, std/[json, strformat]
import chronicles, chronos, results, ffi
import
waku/waku_core/message/message,
waku/waku_core/codecs,
waku/factory/waku,
waku/waku_core/message,
waku/waku_core/topics/pubsub_topic,
waku/waku_lightpush_legacy/client,
waku/node/peer_manager/peer_manager,
logos_delivery/waku/waku_core/message/message,
logos_delivery/waku/waku_core/codecs,
logos_delivery/waku/factory/waku,
logos_delivery/waku/waku_core/message,
logos_delivery/waku/waku_core/topics/pubsub_topic,
logos_delivery/waku/waku_lightpush_legacy/client,
logos_delivery/waku/node/peer_manager/peer_manager,
library/events/json_message_event,
library/declare_lib

View File

@ -1,16 +1,16 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[net, sequtils, strutils, json], strformat
import chronicles, chronos, stew/byteutils, results, ffi
import
waku/waku_core/message/message,
waku/factory/[validator_signed, waku],
logos_delivery/waku/waku_core/message/message,
logos_delivery/waku/factory/[validator_signed, waku],
tools/confutils/cli_args,
waku/waku_core/message,
waku/waku_core/topics/pubsub_topic,
waku/waku_core/topics,
waku/node/kernel_api/relay,
waku/waku_relay/protocol,
waku/node/peer_manager,
logos_delivery/waku/waku_core/message,
logos_delivery/waku/waku_core/topics/pubsub_topic,
logos_delivery/waku/waku_core/topics,
logos_delivery/waku/node/waku_node/relay,
logos_delivery/waku/waku_relay/protocol,
logos_delivery/waku/node/peer_manager,
library/events/json_message_event,
library/declare_lib

View File

@ -1,14 +1,14 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[json, sugar, strutils, options]
import chronos, chronicles, results, stew/byteutils, ffi
import
waku/factory/waku,
logos_delivery/waku/factory/waku,
library/utils,
waku/waku_core/peers,
waku/waku_core/message/digest,
waku/waku_store/common,
waku/waku_store/client,
waku/common/paging,
logos_delivery/waku/waku_core/peers,
logos_delivery/waku/waku_core/message/digest,
logos_delivery/waku/waku_store/common,
logos_delivery/waku/waku_store/client,
logos_delivery/waku/common/paging,
library/declare_lib
func fromJsonNode(jsonContent: JsonNode): Result[StoreQueryRequest, string] =

View File

@ -1,18 +1,18 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[atomics, options, atomics, macros]
import chronicles, chronos, chronos/threadsync, ffi
import
waku/waku_core/message/message,
waku/waku_core/topics/pubsub_topic,
waku/waku_relay,
logos_delivery/waku/waku_core/message/message,
logos_delivery/waku/waku_core/topics/pubsub_topic,
logos_delivery/waku/waku_relay,
./events/json_message_event,
./events/json_topic_health_change_event,
./events/json_connection_change_event,
./events/json_connection_status_change_event,
../waku/factory/app_callbacks,
waku/factory/waku,
waku/node/waku_node,
waku/node/health_monitor/health_status,
../logos_delivery/waku/factory/app_callbacks,
logos_delivery/waku/factory/waku,
logos_delivery/waku/node/waku_node,
logos_delivery/waku/node/health_monitor/health_status,
./declare_lib
################################################################################

View File

@ -3,8 +3,8 @@
## This module re-exports the public API for creating and managing Waku nodes
## when using nwaku as a library dependency.
import waku/api
import logos_delivery/waku/api
export api
import waku/factory/waku
import logos_delivery/waku/factory/waku
export waku

View File

@ -6,8 +6,9 @@ mode = ScriptMode.Verbose
### Package
version = "0.38.1"
author = "Status Research & Development GmbH"
description = "Waku, Private P2P Messaging for Resource-Restricted Devices"
description = "Logos-delivery, Private P2P Messaging for Resource-Restricted Devices"
license = "MIT or Apache License 2.0"
skipDirs = @["tests", "examples", "tools", "apps", "simulations", "metrics"]
const RequiredNimVersion = "2.2.4"
## This is the nim compiler version that we are working on. Other versions may behave differently.
@ -61,19 +62,12 @@ requires "nim >= 2.2.4",
"unittest2"
# Packages not on nimble (use git URLs)
requires "https://github.com/logos-messaging/nim-ffi"
requires "https://github.com/logos-messaging/nim-sds.git#2e9a7683f0e180bf112135fae3a3803eed8490d4"
requires "https://github.com/logos-messaging/nim-ffi#v0.1.3"
# brokers: pinned by URL+commit rather than the bare `brokers >= 2.0.1`
# form because the nim-lang/packages registry entry for `brokers` only
# carries metadata for the original v0.1.0 publication. Until that
# registry entry is refreshed, the local SAT solver enumerates "0.1.0"
# as the only available version and cannot satisfy `>= 2.0.1`. The URL
# pin below bypasses the registry and locks the exact commit of the
# v2.0.1 tag. Revert to the bare form once nim-lang/packages is
# updated.
requires "https://github.com/NagyZoltanPeter/nim-brokers.git#v2.0.1"
requires "https://github.com/logos-messaging/nim-sds.git#abdd40cc645f1b024c3ee99cced7e287c4e4c441"
requires "https://github.com/NagyZoltanPeter/nim-brokers.git#v3.1.1"
requires "https://github.com/vacp2p/nim-lsquic"
requires "https://github.com/vacp2p/nim-jwt.git#057ec95eb5af0eea9c49bfe9025b3312c95dc5f2"
@ -531,3 +525,67 @@ task liblogosdeliveryStaticLinux, "Generate bindings":
task liblogosdeliveryStaticMac, "Generate bindings":
buildLibStaticMac("liblogosdelivery", "liblogosdelivery")
### Formatting tasks
task nphchanges, "Run nph on .nim/.nims/.nimble files changed on this branch/PR":
## Formats every Nim source file that differs from the base branch.
## The set covers committed changes on the branch, working-tree edits
## (staged or not) and untracked files. The base branch is auto-detected
## (origin's default branch, else local main/master); override it with
## the NPH_BASE_BRANCH env var.
let nph =
if findExe("nph").len > 0: findExe("nph")
else: getHomeDir() / ".nimble" / "bin" / "nph"
if not fileExists(nph):
quit "nph not found. Run `make build-nph` first.", 1
proc detectBaseBranch(): string =
# Explicit override wins.
if existsEnv("NPH_BASE_BRANCH"):
return getEnv("NPH_BASE_BRANCH")
# origin's default branch, e.g. "origin/main" -> "main".
let (head, hCode) =
gorgeEx("git symbolic-ref --short refs/remotes/origin/HEAD")
if hCode == 0 and head.strip().len > 0:
let parts = head.strip().split('/')
return parts[^1]
# Fall back to whichever local branch exists.
for candidate in ["main", "master"]:
let (_, vCode) =
gorgeEx("git rev-parse --verify --quiet " & candidate)
if vCode == 0:
return candidate
return "master"
let baseBranch = detectBaseBranch()
# Diff against the merge-base so we only touch what this branch introduced.
var diffRef = baseBranch
let (mergeBase, mbCode) = gorgeEx("git merge-base HEAD " & baseBranch)
if mbCode == 0 and mergeBase.strip().len > 0:
diffRef = mergeBase.strip()
let (changed, dCode) = gorgeEx("git diff --name-only --diff-filter=ACMR " & diffRef)
if dCode != 0:
quit "git diff failed: " & changed, 1
let (untracked, _) = gorgeEx("git ls-files --others --exclude-standard")
var files: seq[string]
for line in (changed & "\n" & untracked).splitLines():
let f = line.strip()
if f.len == 0:
continue
if not (f.endsWith(".nim") or f.endsWith(".nims") or f.endsWith(".nimble")):
continue
if fileExists(f) and f notin files:
files.add(f)
if files.len == 0:
echo "nphchanges: no changed .nim/.nims/.nimble files to format"
return
echo "nphchanges: formatting " & $files.len & " file(s) (base: " & baseBranch & ")"
for f in files:
echo "Formatting " & f
exec nph & " \"" & f & "\""

View File

@ -1,7 +1,7 @@
## Reliable Channel event types emitted to API consumers.
##
## Lifecycle events for individual segments (sent / propagated / errored)
## are the same as the network-level ones the DeliveryService already
## are the same as the network-level ones the MessagingClient already
## emits — `requestId` is shared across layers — so we just re-export
## `waku/events/message_events` and avoid declaring duplicates.
##
@ -9,7 +9,7 @@
## no analogue in the lower layer (reassembled application payload,
## senderId, channelId), so it lives here.
import waku/events/message_events as waku_message_events
import logos_delivery/waku/events/message_events as waku_message_events
import brokers/event_broker
import ./types as channel_types

View File

@ -1,4 +1,4 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
## Reliable Channel type.
##
## A `ReliableChannel` orchestrates segmentation, SDS (end-to-end
@ -21,10 +21,9 @@ import bearssl/rand
import stew/byteutils
import libp2p/crypto/crypto as libp2p_crypto
import waku/api/api
import waku/factory/waku as waku_factory
import waku/node/delivery_service/send_service
import waku/waku_core/topics
import logos_delivery/waku/api/types
import logos_delivery/messaging/delivery_service/send_service
import logos_delivery/waku/waku_core/topics
import ./events
import ./segmentation/segmentation
@ -33,7 +32,7 @@ import ./rate_limit_manager/rate_limit_manager
import ./encryption/encryption
export
api, waku_factory, events, segmentation, scalable_data_sync, rate_limit_manager,
types, send_service, events, segmentation, scalable_data_sync, rate_limit_manager,
encryption
const LipWireReliableChannelVersion* = "RELIABLE-CHANNEL-API/1"
@ -48,9 +47,10 @@ type
SendHandler* = proc(envelope: MessageEnvelope): Future[Result[RequestId, string]] {.
async: (raises: [CatchableError]), gcsafe
.}
## Egress dispatch boundary. Defaults to `waku.send`; tests inject a
## fake that records calls and returns canned `RequestId`s so the
## send state machine can be exercised end-to-end without a network.
## Egress dispatch boundary. Typically wraps `MessagingClient.send`;
## tests inject a fake that records calls and returns canned
## `RequestId`s so the send state machine can be exercised end-to-end
## without a network.
MessagePersistence {.pure.} = enum
Persistent
@ -265,20 +265,22 @@ proc onReadyToSend(
meta: LipWireReliableChannelVersion.toBytes(),
)
## `waku.send` is not annotated `(raises: [])`, but this listener is.
## `sendHandler` is not annotated `(raises: [])`, but this listener is.
## Convert any raise to a Result error so the state machine handles
## both failure modes (Result.err and exception) through one path.
let sendRes =
try:
await self.sendHandler(envelope)
except CatchableError as e:
Result[RequestId, string].err("waku send raised: " & e.msg)
Result[RequestId, string].err("messaging send raised: " & e.msg)
let messagingReqId = sendRes.valueOr:
MessageErrorEvent.emit(
self.brokerCtx,
MessageErrorEvent(
requestId: channelReqId, messageHash: "", error: "waku send failed: " & error
requestId: channelReqId,
messageHash: "",
error: "messaging send failed: " & error,
),
)
self.markSegmentFailed(channelReqId)
@ -375,7 +377,7 @@ proc onMessageReceived(
proc new*(
T: type ReliableChannel,
waku: Waku,
sendHandler: SendHandler,
channelId: ChannelId,
contentTopic: ContentTopic,
senderId: SdsParticipantID,
@ -383,7 +385,6 @@ proc new*(
sdsConfig: SdsConfig,
rateConfig: RateLimitConfig,
brokerCtx: BrokerContext = globalBrokerContext(),
sendHandler: SendHandler = nil,
): T =
## Pipeline handlers (segmentation/SDS/rate-limit) are constructed
## inside the channel rather than handed in by the caller — they are
@ -392,19 +393,11 @@ proc new*(
## `Decrypt` request brokers, so the channel keeps no per-instance
## encryption state either.
##
## `sendHandler` defaults to `waku.send`; tests pass a fake to drive
## the send state machine without touching the network.
let resolvedSendHandler =
if sendHandler.isNil():
proc(
envelope: MessageEnvelope
): Future[Result[RequestId, string]] {.async: (raises: [CatchableError]), gcsafe.} =
return await waku.send(envelope)
else:
sendHandler
## `sendHandler` is the egress dispatch. The owning `ReliableChannelManager`
## typically constructs it as a closure over `MessagingClient.send`. Tests
## pass a fake to drive the send state machine without touching the network.
let chn = T(
sendHandler: resolvedSendHandler,
sendHandler: sendHandler,
channelId: channelId,
contentTopic: contentTopic,
senderId: senderId,

View File

@ -10,12 +10,11 @@ import results
import chronos
import stew/byteutils
import waku/api/api
import waku/api/api_conf
import waku/events/message_events as waku_message_events
import waku/factory/waku as waku_factory
import waku/node/delivery_service/delivery_service
import waku/waku_core/topics
import brokers/broker_context
import logos_delivery/waku/events/message_events as waku_message_events
import logos_delivery/messaging/messaging_client
import logos_delivery/waku/waku_core/topics
import ./reliable_channel
import ./encryption/noop_encryption
@ -24,40 +23,42 @@ export reliable_channel
type ReliableChannelManager* = ref object
channels: Table[ChannelId, ReliableChannel]
waku: Waku
## Owned by the manager. The channel layer reaches the messaging
## API through `waku.send(envelope)`; constructing DeliveryTasks
## directly would breach the layer boundary.
messagingClient: MessagingClient ## Borrowed from the owning `Waku`.
sendHandler: SendHandler
## Default egress dispatch for channels created through this manager.
## Constructed at mount time as a closure over `MessagingClient.send`
## so the channel layer itself stays callable-only.
brokerCtx: BrokerContext
proc new*(
T: type ReliableChannelManager,
conf: WakuNodeConf,
messagingClient: MessagingClient,
sendHandler: SendHandler,
brokerCtx: BrokerContext = globalBrokerContext(),
): Future[Result[T, string]] {.async.} =
## TODO !! The proper ownership chain is:
## ReliableChannelManager -> DeliveryService (MessagingClient) -> Waku (Kernel/Protocols) -> WakuNode,
## and this will be implemented in the future. For now, `createNode`
## is called here to get a Waku instance, and the WakuNode is immediately discarded.
## This is a temporary workaround to get the API
let waku = ?(await createNode(conf))
let manager = T(
channels: initTable[ChannelId, ReliableChannel](), waku: waku, brokerCtx: brokerCtx
): Result[T, string] =
if messagingClient.isNil():
return err("messaging client is required")
if sendHandler.isNil():
return err("sendHandler is required")
return ok(
T(
channels: initTable[ChannelId, ReliableChannel](),
messagingClient: messagingClient,
sendHandler: sendHandler,
brokerCtx: brokerCtx,
)
)
return ok(manager)
proc start*(self: ReliableChannelManager): Result[void, string] =
## Bring the owned DeliveryService up. Separated from `new` so callers
## can register encryption providers / create channels before traffic
## starts flowing.
self.waku.deliveryService.startDeliveryService()
## Placeholder: per-channel listeners are installed in `ReliableChannel.new`,
## so the manager has nothing to start at this layer. Kept for symmetry
## with the `Waku` mount/start lifecycle and as a hook for future state.
discard
ok()
proc stop*(self: ReliableChannelManager) {.async.} =
if not self.waku.isNil():
await self.waku.deliveryService.stopDeliveryService()
## Placeholder mirror of `start`.
discard
proc createReliableChannel*(
self: ReliableChannelManager,
@ -66,17 +67,17 @@ proc createReliableChannel*(
senderId: SdsParticipantID,
sendHandler: SendHandler = nil,
): Result[ChannelId, string] =
## Spec entry point. The `DeliveryService` and `rng` the channel needs
## are sourced from the owning `ReliableChannelManager` rather than
## passed per call. Encryption is wired up through the `Encrypt`/
## `Decrypt` request brokers — the application installs its own
## providers (or `setNoopEncryption()`) before traffic flows.
## Spec entry point. The `sendHandler` and `rng` the channel needs are
## sourced from the owning `ReliableChannelManager` rather than passed
## per call. Encryption is wired up through the `Encrypt`/`Decrypt`
## request brokers — the application installs its own providers
## (or `setNoopEncryption()`) before traffic flows.
##
## Segmentation, SDS and rate-limit configs will eventually be read
## from the node's `NodeConfig`. Defaults for now.
##
## `sendHandler` is left `nil` in production so the channel uses the
## owned `waku.send`; tests pass a fake to bypass the network.
## `sendHandler` defaults to the manager's default (constructed at mount
## from `MessagingClient.send`); tests pass a fake to bypass the network.
if self.channels.hasKey(channelId):
return err("channel already exists: " & channelId)
@ -95,8 +96,10 @@ proc createReliableChannel*(
epochPeriodSec: DefaultEpochPeriodSec, messagesPerEpoch: DefaultMessagesPerEpoch
)
let effectiveSendHandler = if sendHandler.isNil(): self.sendHandler else: sendHandler
let chn = ReliableChannel.new(
waku = self.waku,
sendHandler = effectiveSendHandler,
channelId = channelId,
contentTopic = contentTopic,
senderId = senderId,
@ -104,7 +107,6 @@ proc createReliableChannel*(
sdsConfig = sdsConfig,
rateConfig = rateConfig,
brokerCtx = self.brokerCtx,
sendHandler = sendHandler,
)
self.channels[channelId] = chn
@ -137,5 +139,5 @@ proc send*(
## `ReliableChannel` installs its own `MessageReceivedEvent` listener
## in `ReliableChannel.new`, filters by spec marker and `contentTopic`,
## and routes to its private `onMessageReceived`. This keeps the lower
## layer (MessagingAPI/Waku) unaware of the existence of ReliableChannel
## layer (MessagingClient/Waku) unaware of the existence of ReliableChannel
## and keeps the manager out of per-channel event dispatch.

View File

@ -1,7 +1,7 @@
## Core identifier types for the Reliable Channel API.
import std/hashes
import waku/api/types as api_types
import logos_delivery/waku/api/types as api_types
import ./scalable_data_sync/scalable_data_sync

View File

@ -1,7 +1,9 @@
{.push raises: [].}
import std/[tables, strutils, os], results, chronicles
import ../../../common/databases/db_sqlite, ../../../common/databases/common
import
logos_delivery/waku/common/databases/db_sqlite,
logos_delivery/waku/common/databases/common
logScope:
topics = "waku node delivery_service"

View File

@ -9,9 +9,9 @@
import results
import
../../../common/databases/db_sqlite,
../../../waku_core/message/message,
../../../node/delivery_service/not_delivered_storage/migrations
logos_delivery/waku/common/databases/db_sqlite,
logos_delivery/waku/waku_core/message/message,
./migrations
const NotDeliveredMessagesDbUrl = "not-delivered-messages.db"

View File

@ -1,21 +1,21 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
## This module is in charge of taking care of the messages that this node is expecting to
## receive and is backed by store-v3 requests to get an additional degree of certainty
##
import std/[tables, sequtils, options, sets]
import chronos, chronicles, libp2p/utility
import ../[subscription_manager]
import brokers/broker_context
import
waku/[
logos_delivery/waku/[
waku_core,
waku_core/topics,
waku_store/client,
waku_store/common,
waku_filter_v2/client,
waku_core/topics,
events/message_events,
waku_node,
node/subscription_manager,
]
const StoreCheckPeriod = chronos.minutes(5) ## How often to perform store queries
@ -39,7 +39,6 @@ type RecvService* = ref object of RootObj
brokerCtx: BrokerContext
node: WakuNode
seenMsgListener: MessageSeenEventListener
subscriptionManager: SubscriptionManager
recentReceivedMsgs: seq[RecvMessage]
@ -78,7 +77,9 @@ proc processIncomingMessage(
## or if the message is a duplicate (recently-seen). Otherwise, save it as
## recently-seen, emit a MessageReceivedEvent, and return true.
if not self.subscriptionManager.isSubscribed(pubsubTopic, message.contentTopic):
if not self.node.subscriptionManager.isContentSubscribed(
pubsubTopic, message.contentTopic
):
trace "skipping message as I am not subscribed",
shard = pubsubTopic, contentTopic = message.contentTopic
return false
@ -102,7 +103,7 @@ proc checkStore*(self: RecvService) {.async.} =
self.endTimeToCheck = getNowInNanosecondTime()
## query store and deliver new recovered messages per subscribed topic
for pubsubTopic, contentTopics in self.subscriptionManager.subscribedTopics:
for pubsubTopic, contentTopics in self.node.subscriptionManager.subscribedContentTopics:
let storeResp: StoreQueryResponse = (
await self.node.wakuStoreClient.queryToAny(
StoreQueryRequest(
@ -147,7 +148,7 @@ proc msgChecker(self: RecvService) {.async.} =
await sleepAsync(StoreCheckPeriod)
await self.checkStore()
proc new*(T: typedesc[RecvService], node: WakuNode, s: SubscriptionManager): T =
proc new*(T: typedesc[RecvService], node: WakuNode): T =
## The storeClient will help to acquire any possible missed messages
let now = getNowInNanosecondTime()
@ -155,7 +156,6 @@ proc new*(T: typedesc[RecvService], node: WakuNode, s: SubscriptionManager): T =
node: node,
startTimeToCheck: now,
brokerCtx: node.brokerCtx,
subscriptionManager: s,
recentReceivedMsgs: @[],
)

View File

@ -1,7 +1,10 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[options, times], chronos
import brokers/broker_context
import waku/waku_core, waku/api/types, waku/requests/node_requests
import
logos_delivery/waku/waku_core,
logos_delivery/waku/api/types,
logos_delivery/waku/requests/node_requests
type DeliveryState* {.pure.} = enum
Entry

View File

@ -1,8 +1,11 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import chronicles, chronos, results
import std/options
import brokers/broker_context
import waku/node/peer_manager, waku/waku_core, waku/waku_lightpush/[common, client, rpc]
import
logos_delivery/waku/node/peer_manager,
logos_delivery/waku/waku_core,
logos_delivery/waku/waku_lightpush/[common, client, rpc]
import ./[delivery_task, send_processor]

View File

@ -1,10 +1,10 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/options
import chronos, chronicles
import brokers/broker_context
import waku/[waku_core], waku/waku_lightpush/[common, rpc]
import waku/requests/health_requests
import waku/api/types
import logos_delivery/waku/[waku_core], logos_delivery/waku/waku_lightpush/[common, rpc]
import logos_delivery/waku/requests/health_requests
import logos_delivery/waku/api/types
import ./[delivery_task, send_processor]
logScope:

View File

@ -1,16 +1,16 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
## This module reinforces the publish operation with regular store-v3 requests.
##
import std/[sequtils, tables, options]
import std/[sequtils, tables, options, typetraits]
import chronos, chronicles, libp2p/utility
import brokers/broker_context
import
./[send_processor, relay_processor, lightpush_processor, delivery_task],
../[subscription_manager],
waku/[
logos_delivery/waku/[
waku_core,
node/waku_node,
node/subscription_manager,
node/peer_manager,
waku_store/client,
waku_store/common,
@ -59,7 +59,6 @@ type SendService* = ref object of RootObj
node: WakuNode
checkStoreForMessages: bool
subscriptionManager: SubscriptionManager
proc setupSendProcessorChain(
peerManager: PeerManager,
@ -97,10 +96,7 @@ proc setupSendProcessorChain(
return ok(processors[0])
proc new*(
T: typedesc[SendService],
preferP2PReliability: bool,
w: WakuNode,
s: SubscriptionManager,
T: typedesc[SendService], preferP2PReliability: bool, w: WakuNode
): Result[T, string] =
if w.wakuRelay.isNil() and w.wakuLightpushClient.isNil():
return err(
@ -121,7 +117,6 @@ proc new*(
sendProcessor: sendProcessorChain,
node: w,
checkStoreForMessages: checkStoreForMessages,
subscriptionManager: s,
)
return ok(sendService)
@ -264,7 +259,7 @@ proc send*(self: SendService, task: DeliveryTask) {.async.} =
info "SendService.send: processing delivery task",
requestId = task.requestId, msgHash = task.msgHash.to0xHex()
self.subscriptionManager.subscribe(task.msg.contentTopic).isOkOr:
self.node.subscriptionManager.subscribe(task.msg.contentTopic).isOkOr:
error "SendService.send: failed to subscribe to content topic",
contentTopic = task.msg.contentTopic, error = error

View File

@ -0,0 +1,59 @@
import results, chronos
import chronicles
import
logos_delivery/waku/api/types,
logos_delivery/waku/node/[waku_node, subscription_manager],
logos_delivery/messaging/delivery_service/[recv_service, send_service],
logos_delivery/messaging/delivery_service/send_service/delivery_task
type MessagingClient* = ref object
node: WakuNode
sendService*: SendService
recvService*: RecvService
started: bool
proc new*(
T: type MessagingClient, useP2PReliability: bool, node: WakuNode
): Result[T, string] =
let sendService = ?SendService.new(useP2PReliability, node)
let recvService = RecvService.new(node)
ok(T(node: node, sendService: sendService, recvService: recvService))
proc start*(self: MessagingClient): Result[void, string] =
if self.started:
return ok()
self.recvService.startRecvService()
self.sendService.startSendService()
self.started = true
ok()
proc stop*(self: MessagingClient) {.async.} =
if not self.started:
return
await self.sendService.stopSendService()
await self.recvService.stopRecvService()
self.started = false
proc send*(
self: MessagingClient, envelope: MessageEnvelope
): Future[Result[RequestId, string]] {.async.} =
## High-level messaging API send. Auto-subscribes to the content topic
## (so the local node sees its own gossipsub broadcast), builds a
## `DeliveryTask`, and hands it to the send service. Returns the request
## id the caller can correlate with `MessageSentEvent` / `MessageErrorEvent`.
let isSubbed =
self.node.subscriptionManager.isSubscribed(envelope.contentTopic).valueOr(false)
if not isSubbed:
info "Auto-subscribing to topic on send", contentTopic = envelope.contentTopic
self.node.subscriptionManager.subscribe(envelope.contentTopic).isOkOr:
warn "Failed to auto-subscribe", error = error
return err("Failed to auto-subscribe before sending: " & error)
let requestId = RequestId.new(self.node.rng)
let deliveryTask = DeliveryTask.new(requestId, envelope, self.node.brokerCtx).valueOr:
return err("MessagingClient.send: Failed to create delivery task: " & error)
asyncSpawn self.sendService.send(deliveryTask)
return ok(requestId)

View File

@ -0,0 +1,56 @@
import logos_delivery/waku/compat/option_valueor
import std/[net, options]
import chronicles, chronos, libp2p/peerid, results
import logos_delivery/waku/factory/waku
import logos_delivery/messaging/messaging_client
import logos_delivery/waku/[requests/health_requests, waku_core, waku_node]
import logos_delivery/messaging/delivery_service/send_service
import logos_delivery/waku/node/subscription_manager
import libp2p/peerid
import tools/confutils/cli_args
import ./[api_conf, types]
export cli_args
logScope:
topics = "api"
proc createNode*(conf: WakuNodeConf): Future[Result[Waku, string]] {.async.} =
let wakuConf = conf.toWakuConf().valueOr:
return err("Failed to handle the configuration: " & error)
## We are not defining app callbacks at node creation
let wakuRes = (await Waku.new(wakuConf)).valueOr:
error "waku initialization failed", error = error
return err("Failed setting up Waku: " & $error)
return ok(wakuRes)
proc checkApiAvailability(w: Waku): Result[void, string] =
if w.isNil():
return err("Waku node is not initialized")
# TODO: Conciliate request-bouncing health checks here with unit testing.
# (For now, better to just allow all sends and rely on retries.)
return ok()
proc subscribe*(
w: Waku, contentTopic: ContentTopic
): Future[Result[void, string]] {.async.} =
?checkApiAvailability(w)
return w.node.subscriptionManager.subscribe(contentTopic)
proc unsubscribe*(w: Waku, contentTopic: ContentTopic): Result[void, string] =
?checkApiAvailability(w)
return w.node.subscriptionManager.unsubscribe(contentTopic)
proc send*(
w: Waku, envelope: MessageEnvelope
): Future[Result[RequestId, string]] {.async.} =
?checkApiAvailability(w)
return await w.messagingClient.send(envelope)

View File

@ -1,15 +1,15 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import std/[net, options]
import results
import json_serialization, json_serialization/std/options as json_options
import
waku/common/utils/parse_size_units,
waku/common/logging,
waku/factory/waku_conf,
waku/factory/conf_builder/conf_builder,
waku/factory/networks_config,
logos_delivery/waku/common/utils/parse_size_units,
logos_delivery/waku/common/logging,
logos_delivery/waku/factory/waku_conf,
logos_delivery/waku/factory/conf_builder/conf_builder,
logos_delivery/waku/factory/networks_config,
tools/confutils/entry_nodes
export json_serialization, json_options

View File

@ -1,12 +1,12 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import libp2p/crypto/crypto
{.push raises: [].}
import bearssl/rand, std/times, chronos
import stew/byteutils
import waku/utils/requests as request_utils
import waku/waku_core/[topics/content_topic, message/message, time]
import waku/requests/requests
import logos_delivery/waku/utils/requests as request_utils
import logos_delivery/waku/waku_core/[topics/content_topic, message/message, time]
import logos_delivery/waku/requests/requests
type
MessageEnvelope* = object

View File

@ -1,4 +1,6 @@
import waku/waku_enr/capabilities, waku/waku_rendezvous/waku_peer_record
import
logos_delivery/waku/waku_enr/capabilities,
logos_delivery/waku/waku_rendezvous/waku_peer_record
type GetShards* = proc(): seq[uint16] {.closure, gcsafe, raises: [].}

View File

@ -1,4 +1,4 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
import
std/[times, strutils, os, sets, strformat, tables],
results,

View File

@ -1,4 +1,4 @@
import waku/compat/option_valueor
import logos_delivery/waku/compat/option_valueor
# Simple async pool driver for postgress.
# Inspired by: https://github.com/treeform/pg/
{.push raises: [].}

Some files were not shown because too many files have changed in this diff Show More