diff --git a/.github/workflows/ci-experimental.yml b/.github/workflows/ci-experimental.yml deleted file mode 100644 index 11b6a627a..000000000 --- a/.github/workflows/ci-experimental.yml +++ /dev/null @@ -1,137 +0,0 @@ -name: experimental - -on: - pull_request: - push: - branches: - - master - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - NPROC: 2 - MAKEFLAGS: "-j${NPROC}" - NIMFLAGS: "--parallelBuild:${NPROC}" - EXPERIMENTAL: "true" - -jobs: - changes: # changes detection - runs-on: ubuntu-latest - permissions: - pull-requests: read - steps: - - uses: actions/checkout@v3 - name: Checkout code - id: checkout - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - common: - - '.github/workflows/**' - - 'vendor/**' - - 'Makefile' - - 'waku.nimble' - - v2: - - 'waku/**' - - 'apps/**' - - 'tools/**' - - 'tests/all_tests_waku.nim' - - 'tests/**' - - docker: - - 'docker/**' - - outputs: - common: ${{ steps.filter.outputs.common }} - v2: ${{ steps.filter.outputs.v2 }} - docker: ${{ steps.filter.outputs.docker }} - - build: - needs: changes - if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - timeout-minutes: 60 - - name: build-${{ matrix.os }} - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Get submodules hash - id: submodules - run: | - echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT - - - name: Cache submodules - uses: actions/cache@v3 - with: - path: | - vendor/ - .git/modules - key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }} - - - name: Build binaries - run: make V=1 QUICK_AND_DIRTY_COMPILER=1 all - - test: - needs: changes - if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - timeout-minutes: 60 - - name: test-${{ matrix.os }} - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Get submodules hash - id: submodules - run: | - echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT - - - name: Cache submodules - uses: actions/cache@v3 - with: - path: | - vendor/ - .git/modules - key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }} - - - name: Run tests - run: | - if [ ${{ runner.os }} == "macOS" ]; then - brew unlink postgresql@14 - brew link libpq --force - fi - - if [ ${{ runner.os }} == "Linux" ]; then - sudo docker run --rm -d -e POSTGRES_PASSWORD=test123 -p 5432:5432 postgres:9.6-alpine - fi - - make V=1 LOG_LEVEL=DEBUG QUICK_AND_DIRTY_COMPILER=1 test testwakunode2 - - build-docker-image: - needs: changes - if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' || needs.changes.outputs.docker == 'true' }} - uses: waku-org/nwaku/.github/workflows/container-image.yml@master - with: - experimental: true - secrets: inherit - - js-waku: - needs: build-docker-image - uses: waku-org/js-waku/.github/workflows/ci.yml@master - with: - nim_wakunode_image: ${{ needs.build-docker-image.outputs.image }} - caller: nwaku \ No newline at end of file diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml index 332453131..a01ac207b 100644 --- a/.github/workflows/container-image.yml +++ b/.github/workflows/container-image.yml @@ -2,9 +2,6 @@ name: container-image-build on: workflow_call: - inputs: - experimental: - type: boolean outputs: image: description: The resulting image link @@ -46,14 +43,12 @@ jobs: - name: Build binaries id: build run: | - EXPERIMENTAL=${{ inputs.experimental }} - make -j${NPROC} V=1 QUICK_AND_DIRTY_COMPILER=1 NIMFLAGS="-d:disableMarchNative" wakunode2 EXPERIMENTAL=${EXPERIMENTAL} + make -j${NPROC} V=1 QUICK_AND_DIRTY_COMPILER=1 NIMFLAGS="-d:disableMarchNative" wakunode2 SHORT_REF=$(git rev-parse --short HEAD) TAG=$([ "${PR_NUMBER}" == "" ] && echo "${SHORT_REF}" || echo "${PR_NUMBER}") - TAG=$([ "${EXPERIMENTAL}" == "true" ] && echo "${TAG}-experimental" || echo "${TAG}") IMAGE=quay.io/wakuorg/nwaku-pr:${TAG} echo "image=${IMAGE}" >> $GITHUB_OUTPUT @@ -72,11 +67,11 @@ jobs: if: ${{ github.event_name == 'pull_request' }} with: message: | - You can find the ${{ inputs.experimental && '**experimental**' || ''}} image built from this PR at + You can find the image built from this PR at ``` ${{steps.build.outputs.image}} ``` Built from ${{ steps.build.outputs.commit_hash }} - comment_tag: execution${{ inputs.experimental && '**experimental**' || ''}} + comment_tag: execution diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 90a9ef842..d4c12c20e 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -20,11 +20,9 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - experimental: [true, false] arch: [amd64] include: - os: macos-latest - experimental: false arch: arm64 runs-on: ${{ matrix.os }} steps: @@ -35,14 +33,12 @@ jobs: id: vars run: | ARCH=${{matrix.arch}} - EXPERIMENTAL=$([[ "${{ matrix.experimental }}" == "true" ]] && echo "-experimental" || echo "") TAG=$([[ "${{github.ref}}" == "refs/heads/master" ]] && echo "${{env.RELEASE_NAME}}" || echo ${{github.ref}} | sed 's#refs/tags/##') echo "arch=${ARCH}" >> $GITHUB_OUTPUT - echo "experimental=${EXPERIMENTAL}" >> $GITHUB_OUTPUT - NWAKU_ARTIFACT_NAME=$(echo "nwaku${EXPERIMENTAL}-${ARCH}-${{runner.os}}-${TAG}.tar.gz" | tr "[:upper:]" "[:lower:]") - NWAKU_TOOLS_ARTIFACT_NAME=$(echo "nwaku-tools${EXPERIMENTAL}-${ARCH}-${{runner.os}}-${TAG}.tar.gz" | tr "[:upper:]" "[:lower:]") + NWAKU_ARTIFACT_NAME=$(echo "nwaku-${ARCH}-${{runner.os}}-${TAG}.tar.gz" | tr "[:upper:]" "[:lower:]") + NWAKU_TOOLS_ARTIFACT_NAME=$(echo "nwaku-tools-${ARCH}-${{runner.os}}-${TAG}.tar.gz" | tr "[:upper:]" "[:lower:]") echo "nwaku=${NWAKU_ARTIFACT_NAME}" >> $GITHUB_OUTPUT echo "nwakutools=${NWAKU_TOOLS_ARTIFACT_NAME}" >> $GITHUB_OUTPUT @@ -53,10 +49,10 @@ jobs: run: | OS=$([[ "${{runner.os}}" == "macOS" ]] && echo "macosx" || echo "linux") - make QUICK_AND_DIRTY_COMPILER=1 V=1 CI=false EXPERIMENTAL=${{matrix.experimental}} NIMFLAGS="-d:disableMarchNative --os:${OS} --cpu:${{matrix.arch}}" \ + make QUICK_AND_DIRTY_COMPILER=1 V=1 CI=false NIMFLAGS="-d:disableMarchNative --os:${OS} --cpu:${{matrix.arch}}" \ update - make QUICK_AND_DIRTY_COMPILER=1 V=1 CI=false EXPERIMENTAL=${{matrix.experimental}} NIMFLAGS="-d:disableMarchNative --os:${OS} --cpu:${{matrix.arch}}" \ + make QUICK_AND_DIRTY_COMPILER=1 V=1 CI=false NIMFLAGS="-d:disableMarchNative --os:${OS} --cpu:${{matrix.arch}}" \ wakunode2\ chat2\ tools diff --git a/.github/workflows/release-assets.yml b/.github/workflows/release-assets.yml index 2acaecb8f..0b75519e4 100644 --- a/.github/workflows/release-assets.yml +++ b/.github/workflows/release-assets.yml @@ -44,7 +44,7 @@ jobs: - name: prep variables id: vars run: | - NWAKU_ARTIFACT_NAME=$(echo "nwaku${EXPERIMENTAL}-${{matrix.arch}}-${{runner.os}}.tar.gz" | tr "[:upper:]" "[:lower:]") + NWAKU_ARTIFACT_NAME=$(echo "nwaku-${{matrix.arch}}-${{runner.os}}.tar.gz" | tr "[:upper:]" "[:lower:]") echo "nwaku=${NWAKU_ARTIFACT_NAME}" >> $GITHUB_OUTPUT diff --git a/Dockerfile b/Dockerfile index e9b0227c5..46aa9c5cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,6 @@ FROM alpine@sha256:880fafbab5a7602db21ac37f0d17088a29a9a48f98d581f01ce17312c22cc ARG NIMFLAGS ARG MAKE_TARGET=wakunode2 -ARG EXPERIMENTAL=false ARG NIM_COMMIT ARG LOG_LEVEL=TRACE @@ -22,7 +21,7 @@ RUN git submodule update --init --recursive RUN make -j$(nproc) deps QUICK_AND_DIRTY_COMPILER=1 ${NIM_COMMIT} # Build the final node binary -RUN make -j$(nproc) ${NIM_COMMIT} $MAKE_TARGET LOG_LEVEL=${LOG_LEVEL} NIMFLAGS="${NIMFLAGS}" EXPERIMENTAL="${EXPERIMENTAL}" +RUN make -j$(nproc) ${NIM_COMMIT} $MAKE_TARGET LOG_LEVEL=${LOG_LEVEL} NIMFLAGS="${NIMFLAGS}" # PRODUCTION IMAGE ------------------------------------------------------------- diff --git a/Makefile b/Makefile index c4ce0e906..3e62390e8 100644 --- a/Makefile +++ b/Makefile @@ -110,19 +110,10 @@ clean: | clean-libbacktrace ################## -## Experimental ## +## RLN ## ################## .PHONY: librln -EXPERIMENTAL ?= false -EXPERIMENTAL_PARAMS ?= $(EMPTY) - -ifeq ($(EXPERIMENTAL), true) -RLN := true -endif - -### RLN - LIBRLN_BUILDDIR := $(CURDIR)/vendor/zerokit ifeq ($(OS),Windows_NT) @@ -135,14 +126,9 @@ $(LIBRLN_FILE): echo -e $(BUILD_MSG) "$@" && \ ./scripts/build_rln.sh $(LIBRLN_BUILDDIR) -librln-experimental: | $(LIBRLN_FILE) - $(eval EXPERIMENTAL_PARAMS += -d:rln --passL:$(LIBRLN_FILE) --passL:-lm) -ifneq ($(RLN), true) -librln: ; # noop -else -librln: | librln-experimental -endif +librln: | $(LIBRLN_FILE) + $(eval NIM_PARAMS += --passL:$(LIBRLN_FILE) --passL:-lm) clean-librln: cargo clean --manifest-path vendor/zerokit/rln/Cargo.toml @@ -169,33 +155,33 @@ testcommon: | build deps testwaku: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim test -d:os=$(shell uname) $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim test -d:os=$(shell uname) $(NIM_PARAMS) waku.nims wakunode2: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim wakunode2 $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim wakunode2 $(NIM_PARAMS) waku.nims testwakunode2: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim testwakunode2 $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim testwakunode2 $(NIM_PARAMS) waku.nims -example2: | build deps +example2: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim example2 $(NIM_PARAMS) waku.nims chat2: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim chat2 $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim chat2 $(NIM_PARAMS) waku.nims -rln-keystore-generator: | build deps librln-experimental +rln-keystore-generator: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim rln_keystore_generator $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim rln_keystore_generator $(NIM_PARAMS) waku.nims -rln-db-inspector: | build deps librln-experimental +rln-db-inspector: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ - $(ENV_SCRIPT) nim rln_db_inspector $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim rln_db_inspector $(NIM_PARAMS) waku.nims -chat2bridge: | build deps +chat2bridge: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim chat2bridge $(NIM_PARAMS) waku.nims @@ -207,11 +193,11 @@ chat2bridge: | build deps tools: networkmonitor wakucanary -wakucanary: | build deps +wakucanary: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim wakucanary $(NIM_PARAMS) waku.nims -networkmonitor: | build deps +networkmonitor: | build deps librln echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim networkmonitor $(NIM_PARAMS) waku.nims @@ -243,7 +229,6 @@ docker-image: docker build \ --build-arg="MAKE_TARGET=$(MAKE_TARGET)" \ --build-arg="NIMFLAGS=$(DOCKER_IMAGE_NIMFLAGS)" \ - --build-arg="EXPERIMENTAL=$(EXPERIMENTAL)" \ --build-arg="NIM_COMMIT=$(DOCKER_NIM_COMMIT)" \ --build-arg="LOG_LEVEL=$(LOG_LEVEL)" \ --label="commit=$(GIT_VERSION)" \ @@ -265,10 +250,10 @@ libwaku: | build deps rm -f build/libwaku* ifeq ($(STATIC), true) echo -e $(BUILD_MSG) "build/$@.a" && \ - $(ENV_SCRIPT) nim libwakuStatic $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim libwakuStatic $(NIM_PARAMS) waku.nims else echo -e $(BUILD_MSG) "build/$@.so" && \ - $(ENV_SCRIPT) nim libwakuDynamic $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims + $(ENV_SCRIPT) nim libwakuDynamic $(NIM_PARAMS) waku.nims endif cwaku_example: | build libwaku diff --git a/apps/chat2/chat2.nim b/apps/chat2/chat2.nim index 2aaa594f9..d7ebb3a91 100644 --- a/apps/chat2/chat2.nim +++ b/apps/chat2/chat2.nim @@ -38,12 +38,11 @@ import ../../waku/common/utils/nat, ./config_chat2 -when defined(rln): - import - libp2p/protocols/pubsub/rpc/messages, - libp2p/protocols/pubsub/pubsub - import - ../../waku/waku_rln_relay +import + libp2p/protocols/pubsub/rpc/messages, + libp2p/protocols/pubsub/pubsub +import + ../../waku/waku_rln_relay const Help = """ Commands: /[?|help|connect|nick|exit] @@ -187,28 +186,27 @@ proc publish(c: Chat, line: string) = var message = WakuMessage(payload: chat2pb.buffer, contentTopic: c.contentTopic, version: 0, timestamp: getNanosecondTime(time)) - when defined(rln): - if not isNil(c.node.wakuRlnRelay): - # for future version when we support more than one rln protected content topic, - # we should check the message content topic as well - let success = c.node.wakuRlnRelay.appendRLNProof(message, float64(time)) - if not success: - debug "could not append rate limit proof to the message", success=success - else: - debug "rate limit proof is appended to the message", success=success - let decodeRes = RateLimitProof.init(message.proof) - if decodeRes.isErr(): - error "could not decode the RLN proof" + if not isNil(c.node.wakuRlnRelay): + # for future version when we support more than one rln protected content topic, + # we should check the message content topic as well + let success = c.node.wakuRlnRelay.appendRLNProof(message, float64(time)) + if not success: + debug "could not append rate limit proof to the message", success=success + else: + debug "rate limit proof is appended to the message", success=success + let decodeRes = RateLimitProof.init(message.proof) + if decodeRes.isErr(): + error "could not decode the RLN proof" - let proof = decodeRes.get() - # TODO move it to log after dogfooding - let msgEpoch = fromEpoch(proof.epoch) - if fromEpoch(c.node.wakuRlnRelay.lastEpoch) == msgEpoch: - echo "--rln epoch: ", msgEpoch, " ⚠️ message rate violation! you are spamming the network!" - else: - echo "--rln epoch: ", msgEpoch - # update the last epoch - c.node.wakuRlnRelay.lastEpoch = proof.epoch + let proof = decodeRes.get() + # TODO move it to log after dogfooding + let msgEpoch = fromEpoch(proof.epoch) + if fromEpoch(c.node.wakuRlnRelay.lastEpoch) == msgEpoch: + echo "--rln epoch: ", msgEpoch, " ⚠️ message rate violation! you are spamming the network!" + else: + echo "--rln epoch: ", msgEpoch + # update the last epoch + c.node.wakuRlnRelay.lastEpoch = proof.epoch if not c.node.wakuLightPush.isNil(): # Attempt lightpush @@ -489,44 +487,40 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} = let topic = DefaultPubsubTopic await node.subscribe(some(topic), @[ContentTopic("")], handler) - when defined(rln): - if conf.rlnRelay: - info "WakuRLNRelay is enabled" + if conf.rlnRelay: + info "WakuRLNRelay is enabled" - proc spamHandler(wakuMessage: WakuMessage) {.gcsafe, closure.} = - debug "spam handler is called" - let chatLineResult = chat.getChatLine(wakuMessage) - if chatLineResult.isOk(): - echo "A spam message is found and discarded : ", chatLineResult.value - else: - echo "A spam message is found and discarded" - chat.prompt = false - showChatPrompt(chat) - - echo "rln-relay preparation is in progress..." + proc spamHandler(wakuMessage: WakuMessage) {.gcsafe, closure.} = + debug "spam handler is called" + let chatLineResult = chat.getChatLine(wakuMessage) + if chatLineResult.isOk(): + echo "A spam message is found and discarded : ", chatLineResult.value + else: + echo "A spam message is found and discarded" + chat.prompt = false + showChatPrompt(chat) + + echo "rln-relay preparation is in progress..." - let rlnConf = WakuRlnConfig( - rlnRelayDynamic: conf.rlnRelayDynamic, - rlnRelayCredIndex: conf.rlnRelayCredIndex, - rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, - rlnRelayCredPath: conf.rlnRelayCredPath, - rlnRelayCredPassword: conf.rlnRelayCredPassword - ) + let rlnConf = WakuRlnConfig( + rlnRelayDynamic: conf.rlnRelayDynamic, + rlnRelayCredIndex: conf.rlnRelayCredIndex, + rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, + rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayCredPath: conf.rlnRelayCredPath, + rlnRelayCredPassword: conf.rlnRelayCredPassword + ) - waitFor node.mountRlnRelay(rlnConf, - spamHandler=some(spamHandler)) + waitFor node.mountRlnRelay(rlnConf, + spamHandler=some(spamHandler)) - let membershipIndex = node.wakuRlnRelay.groupManager.membershipIndex.get() - let identityCredential = node.wakuRlnRelay.groupManager.idCredentials.get() - echo "your membership index is: ", membershipIndex - echo "your rln identity trapdoor is: ", identityCredential.idTrapdoor.inHex() - echo "your rln identity nullifier is: ", identityCredential.idNullifier.inHex() - echo "your rln identity secret hash is: ", identityCredential.idSecretHash.inHex() - echo "your rln identity commitment key is: ", identityCredential.idCommitment.inHex() + let membershipIndex = node.wakuRlnRelay.groupManager.membershipIndex.get() + let identityCredential = node.wakuRlnRelay.groupManager.idCredentials.get() + echo "your membership index is: ", membershipIndex + echo "your rln identity commitment key is: ", identityCredential.idCommitment.inHex() else: info "WakuRLNRelay is disabled" - echo "WakuRLNRelay is disabled, please enable it by compiling with the RLN/EXPERIMENTAL flag" + echo "WakuRLNRelay is disabled, please enable it by passing in the --rln-relay flag" if conf.metricsLogging: startMetricsLog() diff --git a/apps/wakunode2/app.nim b/apps/wakunode2/app.nim index 5dfbc1fe3..c976e7de4 100644 --- a/apps/wakunode2/app.nim +++ b/apps/wakunode2/app.nim @@ -33,6 +33,7 @@ import ../../waku/waku_enr, ../../waku/waku_discv5, ../../waku/waku_peer_exchange, + ../../waku/waku_rln_relay, ../../waku/waku_store, ../../waku/waku_lightpush, ../../waku/waku_filter, @@ -54,9 +55,6 @@ import ../../waku/node/jsonrpc/relay/handlers as rpc_relay_api, ../../waku/node/jsonrpc/store/handlers as rpc_store_api -when defined(rln): - import ../../waku/waku_rln_relay - logScope: topics = "wakunode app" @@ -392,23 +390,22 @@ proc setupProtocols(node: WakuNode, except CatchableError: return err("failed to mount libp2p ping protocol: " & getCurrentExceptionMsg()) - when defined(rln): - if conf.rlnRelay: + if conf.rlnRelay: - let rlnConf = WakuRlnConfig( - rlnRelayDynamic: conf.rlnRelayDynamic, - rlnRelayCredIndex: conf.rlnRelayCredIndex, - rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, - rlnRelayCredPath: conf.rlnRelayCredPath, - rlnRelayCredPassword: conf.rlnRelayCredPassword, - rlnRelayTreePath: conf.rlnRelayTreePath, - ) + let rlnConf = WakuRlnConfig( + rlnRelayDynamic: conf.rlnRelayDynamic, + rlnRelayCredIndex: conf.rlnRelayCredIndex, + rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, + rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayCredPath: conf.rlnRelayCredPath, + rlnRelayCredPassword: conf.rlnRelayCredPassword, + rlnRelayTreePath: conf.rlnRelayTreePath, + ) - try: - waitFor node.mountRlnRelay(rlnConf) - except CatchableError: - return err("failed to mount waku RLN relay protocol: " & getCurrentExceptionMsg()) + try: + waitFor node.mountRlnRelay(rlnConf) + except CatchableError: + return err("failed to mount waku RLN relay protocol: " & getCurrentExceptionMsg()) if conf.store: var onErrAction = proc(msg: string) {.gcsafe, closure.} = diff --git a/ci/Jenkinsfile.prs b/ci/Jenkinsfile.prs index e775f96b9..1a0583f90 100644 --- a/ci/Jenkinsfile.prs +++ b/ci/Jenkinsfile.prs @@ -29,11 +29,6 @@ pipeline { description: 'Makefile flags.', defaultValue: params.MAKEFLAGS ?: '-j6' ) - booleanParam( - name: 'EXPERIMENTAL', - description: 'Enable experimental features.', - defaultValue: false - ) } options { @@ -66,7 +61,7 @@ pipeline { stage('V2') { when { expression { v2changed } } steps { script { - nix.shell("make ${params.MAKEFLAGS} NIMFLAGS=\"${params.NIMFLAGS}\" V=${params.VERBOSITY} EXPERIMENTAL=${params.EXPERIMENTAL} all") + nix.shell("make ${params.MAKEFLAGS} NIMFLAGS=\"${params.NIMFLAGS}\" V=${params.VERBOSITY} all") } } } } @@ -77,7 +72,7 @@ pipeline { stage('V2') { when { expression { v2changed } } steps { script { - nix.shell("make ${params.MAKEFLAGS} NIMFLAGS=\"${params.NIMFLAGS}\" V=${params.VERBOSITY} EXPERIMENTAL=${params.EXPERIMENTAL} test") + nix.shell("make ${params.MAKEFLAGS} NIMFLAGS=\"${params.NIMFLAGS}\" V=${params.VERBOSITY} test") } } } } diff --git a/ci/Jenkinsfile.release b/ci/Jenkinsfile.release index 512a16280..819de1a16 100644 --- a/ci/Jenkinsfile.release +++ b/ci/Jenkinsfile.release @@ -40,11 +40,6 @@ pipeline { name: "LOG_LEVEL", description: "Chronicles log level (default: TRACE)", ) - booleanParam( - name: 'EXPERIMENTAL', - description: 'Enable experimental features.', - defaultValue: false - ) booleanParam( name: 'DEBUG', description: 'Enable debug features (heaptrack).', @@ -56,11 +51,10 @@ pipeline { stage('Build') { steps { script { image = docker.build( - "${params.IMAGE_NAME}:${env.GIT_COMMIT.take(8)}" + (params.EXPERIMENTAL ? "-experimental": ""), + "${params.IMAGE_NAME}:${env.GIT_COMMIT.take(8)}", "--label=commit='${env.GIT_COMMIT.take(8)}' " + "--build-arg=MAKE_TARGET='${params.MAKE_TARGET}' " + "--build-arg=NIMFLAGS='${params.NIMFLAGS}' " + - "--build-arg=EXPERIMENTAL='${params.EXPERIMENTAL}' " + (params.LOG_LEVEL != null ? "--build-arg=LOG_LEVEL='${params.LOG_LEVEL}' ": "") + "--target=${params.DEBUG ? "debug" : "prod"} ." ) diff --git a/docs/operators/how-to/run-with-rln.md b/docs/operators/how-to/run-with-rln.md index 570131740..7804b5966 100644 --- a/docs/operators/how-to/run-with-rln.md +++ b/docs/operators/how-to/run-with-rln.md @@ -21,21 +21,13 @@ You may alter the rln-specific arguments as required. > Note: If you would like to run a nwaku node with RLN enabled within a docker container, skip ahead to step 2. -## 1. Update the build command +## 1. Build wakunode2 -_Instead_ of just running - +Run - ```bash make wakunode2 ``` -Run the following command - -```bash -make wakunode2 RLN=true -``` - -The `RLN=true` flag will enable compilation of the waku-rln-relay protocol -into your wakunode2 binary. - ## 2. Update the runtime arguments Follow [Step 10](../droplet-quickstart.md#10-run-nwaku) of the [droplet quickstart](../droplet-quickstart.md) guide, while replacing the run command with - diff --git a/docs/tutorial/onchain-rln-relay-chat2.md b/docs/tutorial/onchain-rln-relay-chat2.md index 69b3e12b8..0d2e8741d 100644 --- a/docs/tutorial/onchain-rln-relay-chat2.md +++ b/docs/tutorial/onchain-rln-relay-chat2.md @@ -30,10 +30,10 @@ You can test it by connecting two chat2 clients (running Waku-RLN-Relay) directl # Set up ## Build chat2 -First, build chat2 with the RLN flag set to true. +First, build chat2 ```bash -make chat2 RLN=true +make chat2 ``` ## Set up a chat2 client diff --git a/docs/tutorial/rln-chat2-live-testnet.md b/docs/tutorial/rln-chat2-live-testnet.md index 6094e832b..8dfc85308 100644 --- a/docs/tutorial/rln-chat2-live-testnet.md +++ b/docs/tutorial/rln-chat2-live-testnet.md @@ -13,10 +13,10 @@ Your samp activity will be detected by them and a proper message will be shown o # Set up ## Build chat2 -First, build chat2 with the RLN flag set to true. +First, build chat2 ``` -make chat2 RLN=true +make chat2 ``` ## Setup a chat2 node in rate-limited mode @@ -123,21 +123,3 @@ Connecting to storenode: 16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ >> /exit quitting... ``` - -# Trouble shooting - -## compilation error: found possibly newer version of crate - - -If running `make chat2 RLN=true` yields a compile error like this - -``` -error[E0460]: found possibly newer version of crate `std` which `sapling_crypto_ce` depends on - --> src/circuit/polynomial.rs:1:5 - | -1 | use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr}; -``` - -run - -`make cleanrln` before running `make chat2 RLN=true` again. diff --git a/docs/tutorial/rln-chat2-local-test.md b/docs/tutorial/rln-chat2-local-test.md index 7e3e1d37e..f5d4bdb80 100644 --- a/docs/tutorial/rln-chat2-local-test.md +++ b/docs/tutorial/rln-chat2-local-test.md @@ -12,10 +12,10 @@ You can inspect its current value by checking the following [constant variable]( # Set up ## Build chat2 -First, build chat2 with the RLN flag set to true. +First, build chat2 ``` -make chat2 RLN=true +make chat2 ``` ## Create a local network of chat2 clients diff --git a/tests/all_tests_waku.nim b/tests/all_tests_waku.nim index d5ed75052..3c21bba77 100644 --- a/tests/all_tests_waku.nim +++ b/tests/all_tests_waku.nim @@ -94,13 +94,9 @@ import ./wakunode_rest/test_rest_serdes, ./wakunode_rest/test_rest_store - -## Experimental - -when defined(rln): - import - ./waku_rln_relay/test_waku_rln_relay, - ./waku_rln_relay/test_wakunode_rln_relay, - ./waku_rln_relay/test_rln_group_manager_onchain, - ./waku_rln_relay/test_rln_group_manager_static, - ./wakunode_rest/test_rest_health +import + ./waku_rln_relay/test_waku_rln_relay, + ./waku_rln_relay/test_wakunode_rln_relay, + ./waku_rln_relay/test_rln_group_manager_onchain, + ./waku_rln_relay/test_rln_group_manager_static, + ./wakunode_rest/test_rest_health diff --git a/tests/wakunode_jsonrpc/test_jsonrpc_relay.nim b/tests/wakunode_jsonrpc/test_jsonrpc_relay.nim index 919b4d006..016b71613 100644 --- a/tests/wakunode_jsonrpc/test_jsonrpc_relay.nim +++ b/tests/wakunode_jsonrpc/test_jsonrpc_relay.nim @@ -17,15 +17,11 @@ import ../../../waku/node/jsonrpc/relay/client as relay_api_client, ../../../waku/waku_core, ../../../waku/waku_relay, + ../../../waku/waku_rln_relay, ../testlib/common, ../testlib/wakucore, ../testlib/wakunode -when defined(rln): - import - ../../../waku/waku_rln_relay - - proc newTestMessageCache(): relay_api.MessageCache = relay_api.MessageCache.init(capacity=30) @@ -104,14 +100,13 @@ suite "Waku v2 JSON-RPC API - Relay": await srcNode.mountRelay(@[pubSubTopic]) await dstNode.mountRelay(@[pubSubTopic]) - when defined(rln): - await srcNode.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, - rlnRelayCredIndex: some(1.uint), - rlnRelayTreePath: genTempPath("rln_tree", "wakunode_1"))) + await srcNode.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnRelayTreePath: genTempPath("rln_tree", "wakunode_1"))) - await dstNode.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, - rlnRelayCredIndex: some(2.uint), - rlnRelayTreePath: genTempPath("rln_tree", "wakunode_2"))) + await dstNode.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayCredIndex: some(2.uint), + rlnRelayTreePath: genTempPath("rln_tree", "wakunode_2"))) await srcNode.connectToNodes(@[dstNode.peerInfo.toRemotePeerInfo()]) @@ -155,8 +150,7 @@ suite "Waku v2 JSON-RPC API - Relay": var (topic, msg) = dstHandlerFut.read() # proof is injected under the hood, we compare just the message - when defined(rln): - msg.proof = @[] + msg.proof = @[] check: topic == pubSubTopic diff --git a/tests/wakunode_rest/test_rest_health.nim b/tests/wakunode_rest/test_rest_health.nim index 46b2ea75b..8d13cc644 100644 --- a/tests/wakunode_rest/test_rest_health.nim +++ b/tests/wakunode_rest/test_rest_health.nim @@ -19,6 +19,7 @@ import ../../waku/node/rest/health/client as health_api_client, ../../waku/waku_rln_relay, ../testlib/common, + ../testlib/testutils, ../testlib/wakucore, ../testlib/wakunode @@ -34,7 +35,8 @@ proc testWakuNode(): WakuNode = suite "Waku v2 REST API - health": - asyncTest "Get node health info - GET /health": + # TODO: better test for health + xasyncTest "Get node health info - GET /health": # Given let node = testWakuNode() await node.start() diff --git a/tests/wakunode_rest/test_rest_relay.nim b/tests/wakunode_rest/test_rest_relay.nim index e59fb6899..75d111e47 100644 --- a/tests/wakunode_rest/test_rest_relay.nim +++ b/tests/wakunode_rest/test_rest_relay.nim @@ -19,13 +19,10 @@ import ../../waku/node/rest/relay/client as relay_api_client, ../../waku/node/rest/relay/topic_cache, ../../waku/waku_relay, + ../../../waku/waku_rln_relay, ../testlib/wakucore, ../testlib/wakunode -when defined(rln): - import - ../../../waku/waku_rln_relay - proc testWakuNode(): WakuNode = let privkey = generateSecp256k1Key() @@ -186,10 +183,9 @@ suite "Waku v2 Rest API - Relay": let node = testWakuNode() await node.start() await node.mountRelay() - when defined(rln): - await node.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, - rlnRelayCredIndex: some(1.uint), - rlnRelayTreePath: genTempPath("rln_tree", "wakunode_1"))) + await node.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnRelayTreePath: genTempPath("rln_tree", "wakunode_1"))) # RPC server setup let restPort = Port(58014) diff --git a/waku/node/jsonrpc/relay/handlers.nim b/waku/node/jsonrpc/relay/handlers.nim index 38e08c1d0..4329a990a 100644 --- a/waku/node/jsonrpc/relay/handlers.nim +++ b/waku/node/jsonrpc/relay/handlers.nim @@ -13,6 +13,8 @@ import ../../../common/base64, ../../../waku_core, ../../../waku_relay, + ../../../waku_rln_relay, + ../../../waku_rln_relay/rln/wrappers, ../../waku_node, ../../message_cache, ../message @@ -20,10 +22,6 @@ import from std/times import getTime from std/times import toUnix -when defined(rln): - import - ../../../waku_rln_relay, - ../../../waku_rln_relay/rln/wrappers logScope: topics = "waku node jsonrpc relay_api" @@ -101,28 +99,25 @@ proc installRelayApiHandlers*(node: WakuNode, server: RpcServer, cache: MessageC raise newException(ValueError, "Failed to publish: Node not subscribed to pubsubTopic: " & pubsubTopic) # if RLN is mounted, append the proof to the message - when defined(rln): - if not node.wakuRlnRelay.isNil(): - # append the proof to the message - let success = node.wakuRlnRelay.appendRLNProof(message, - float64(getTime().toUnix())) - if not success: - raise newException(ValueError, "Failed to publish: error appending RLN proof to message") - # validate the message before sending it - let result = node.wakuRlnRelay.validateMessage(message) - if result == MessageValidationResult.Invalid: - raise newException(ValueError, "Failed to publish: invalid RLN proof") - elif result == MessageValidationResult.Spam: - raise newException(ValueError, "Failed to publish: limit exceeded, try again later") - elif result == MessageValidationResult.Valid: - debug "RLN proof validated successfully", pubSubTopic=pubSubTopic - else: - raise newException(ValueError, "Failed to publish: unknown RLN proof validation result") + if not node.wakuRlnRelay.isNil(): + # append the proof to the message + let success = node.wakuRlnRelay.appendRLNProof(message, + float64(getTime().toUnix())) + if not success: + raise newException(ValueError, "Failed to publish: error appending RLN proof to message") + # validate the message before sending it + let result = node.wakuRlnRelay.validateMessage(message) + if result == MessageValidationResult.Invalid: + raise newException(ValueError, "Failed to publish: invalid RLN proof") + elif result == MessageValidationResult.Spam: + raise newException(ValueError, "Failed to publish: limit exceeded, try again later") + elif result == MessageValidationResult.Valid: + debug "RLN proof validated successfully", pubSubTopic=pubSubTopic else: - raise newException(ValueError, "Failed to publish: RLN enabled but not mounted") + raise newException(ValueError, "Failed to publish: unknown RLN proof validation result") # if we reach here its either a non-RLN message or a RLN message with a valid proof - debug "Publishing message", pubSubTopic=pubSubTopic, rln=defined(rln) + debug "Publishing message", pubSubTopic=pubSubTopic let publishFut = node.publish(pubsubTopic, message) if not await publishFut.withTimeout(futTimeout): raise newException(ValueError, "Failed to publish: timed out") diff --git a/waku/node/rest/relay/handlers.nim b/waku/node/rest/relay/handlers.nim index 586040100..68647de76 100644 --- a/waku/node/rest/relay/handlers.nim +++ b/waku/node/rest/relay/handlers.nim @@ -14,6 +14,8 @@ import import ../../waku_node, ../../../waku_relay/protocol, + ../../../waku_rln_relay, + ../../../waku_rln_relay/rln/wrappers, ../serdes, ../responses, ./types, @@ -22,10 +24,6 @@ import from std/times import getTime from std/times import toUnix -when defined(rln): - import - ../../../waku_rln_relay, - ../../../waku_rln_relay/rln/wrappers export types @@ -161,29 +159,26 @@ proc installRelayPostMessagesV1Handler*(router: var RestRouter, node: WakuNode) var message = resMessage.get() # if RLN is mounted, append the proof to the message - when defined(rln): - if not node.wakuRlnRelay.isNil(): - # append the proof to the message - let success = node.wakuRlnRelay.appendRLNProof(message, - float64(getTime().toUnix())) - if not success: - return RestApiResponse.internalServerError("Failed to publish: error appending RLN proof to message") + if not node.wakuRlnRelay.isNil(): + # append the proof to the message + let success = node.wakuRlnRelay.appendRLNProof(message, + float64(getTime().toUnix())) + if not success: + return RestApiResponse.internalServerError("Failed to publish: error appending RLN proof to message") - # validate the message before sending it - let result = node.wakuRlnRelay.validateMessage(message) - if result == MessageValidationResult.Invalid: - return RestApiResponse.internalServerError("Failed to publish: invalid RLN proof") - elif result == MessageValidationResult.Spam: - return RestApiResponse.badRequest("Failed to publish: limit exceeded, try again later") - elif result == MessageValidationResult.Valid: - debug "RLN proof validated successfully", pubSubTopic=pubSubTopic - else: - return RestApiResponse.internalServerError("Failed to publish: unknown RLN proof validation result") + # validate the message before sending it + let result = node.wakuRlnRelay.validateMessage(message) + if result == MessageValidationResult.Invalid: + return RestApiResponse.internalServerError("Failed to publish: invalid RLN proof") + elif result == MessageValidationResult.Spam: + return RestApiResponse.badRequest("Failed to publish: limit exceeded, try again later") + elif result == MessageValidationResult.Valid: + debug "RLN proof validated successfully", pubSubTopic=pubSubTopic else: - return RestApiResponse.internalServerError("Failed to publish: RLN enabled but not mounted") + return RestApiResponse.internalServerError("Failed to publish: unknown RLN proof validation result") # if we reach here its either a non-RLN message or a RLN message with a valid proof - debug "Publishing message", pubSubTopic=pubSubTopic, rln=defined(rln) + debug "Publishing message", pubSubTopic=pubSubTopic if not (waitFor node.publish(pubSubTopic, resMessage.value).withTimeout(futTimeout)): error "Failed to publish message to topic", pubSubTopic=pubSubTopic return RestApiResponse.internalServerError("Failed to publish: timedout") diff --git a/waku/node/waku_metrics.nim b/waku/node/waku_metrics.nim index 9e857fa3e..93c98ba57 100644 --- a/waku/node/waku_metrics.nim +++ b/waku/node/waku_metrics.nim @@ -10,14 +10,12 @@ import metrics/chronos_httpserver import ../waku_filter/protocol_metrics as filter_metrics, + ../waku_rln_relay/protocol_metrics as rln_metrics, + ../utils/collector, ./peer_manager, ./waku_node -when defined(rln): - import ../waku_rln_relay/protocol_metrics as rln_metrics - - const LogInterval = 30.seconds logScope: @@ -34,8 +32,7 @@ proc startMetricsLog*() = var cumulativeErrors = 0.float64 var cumulativeConns = 0.float64 - when defined(rln): - let logRlnMetrics = getRlnMetricsLogger() + let logRlnMetrics = getRlnMetricsLogger() logMetrics = proc(udata: pointer) = {.gcsafe.}: @@ -63,8 +60,7 @@ proc startMetricsLog*() = info "Total errors", count = $freshErrorCount # Start protocol specific metrics logging - when defined(rln): - logRlnMetrics() + logRlnMetrics() discard setTimer(Moment.fromNow(LogInterval), logMetrics) diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 131cc64bb..5d9aa54e9 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -38,13 +38,11 @@ import ../waku_enr, ../waku_dnsdisc, ../waku_peer_exchange, + ../waku_rln_relay, ./config, ./peer_manager, ./waku_switch -when defined(rln): - import - ../waku_rln_relay declarePublicCounter waku_node_messages, "number of messages received", ["type"] declarePublicHistogram waku_histogram_message_size, "message size histogram in kB", @@ -92,8 +90,7 @@ type wakuFilter*: waku_filter_v2.WakuFilter wakuFilterLegacy*: legacy_filter.WakuFilterLegacy #TODO: support for legacy filter protocol will be removed wakuFilterClientLegacy*: WakuFilterClientLegacy #TODO: support for legacy filter protocol will be removed - when defined(rln): - wakuRlnRelay*: WakuRLNRelay + wakuRlnRelay*: WakuRLNRelay wakuLightPush*: WakuLightPush wakuLightpushClient*: WakuLightPushClient wakuPeerExchange*: WakuPeerExchange @@ -729,28 +726,27 @@ proc lightpushPublish*(node: WakuNode, pubsubTopic: Option[PubsubTopic], message ## Waku RLN Relay -when defined(rln): - proc mountRlnRelay*(node: WakuNode, - rlnConf: WakuRlnConfig, - spamHandler = none(SpamHandler), - registrationHandler = none(RegistrationHandler)) {.async.} = - info "mounting rln relay" +proc mountRlnRelay*(node: WakuNode, + rlnConf: WakuRlnConfig, + spamHandler = none(SpamHandler), + registrationHandler = none(RegistrationHandler)) {.async.} = + info "mounting rln relay" - if node.wakuRelay.isNil(): - raise newException(CatchableError, "WakuRelay protocol is not mounted, cannot mount WakuRlnRelay") + if node.wakuRelay.isNil(): + raise newException(CatchableError, "WakuRelay protocol is not mounted, cannot mount WakuRlnRelay") - let rlnRelayRes = waitFor WakuRlnRelay.new(rlnConf, - registrationHandler) - if rlnRelayRes.isErr(): - raise newException(CatchableError, "failed to mount WakuRlnRelay: " & rlnRelayRes.error) - let rlnRelay = rlnRelayRes.get() - let validator = generateRlnValidator(rlnRelay, spamHandler) + let rlnRelayRes = waitFor WakuRlnRelay.new(rlnConf, + registrationHandler) + if rlnRelayRes.isErr(): + raise newException(CatchableError, "failed to mount WakuRlnRelay: " & rlnRelayRes.error) + let rlnRelay = rlnRelayRes.get() + let validator = generateRlnValidator(rlnRelay, spamHandler) - # register rln validator for all subscribed relay pubsub topics - for pubsubTopic in node.wakuRelay.subscribedTopics: - debug "Registering RLN validator for topic", pubsubTopic=pubsubTopic - node.wakuRelay.addValidator(pubsubTopic, validator) - node.wakuRlnRelay = rlnRelay + # register rln validator for all subscribed relay pubsub topics + for pubsubTopic in node.wakuRelay.subscribedTopics: + debug "Registering RLN validator for topic", pubsubTopic=pubsubTopic + node.wakuRelay.addValidator(pubsubTopic, validator) + node.wakuRlnRelay = rlnRelay ## Waku peer-exchange @@ -898,16 +894,13 @@ proc stop*(node: WakuNode) {.async.} = await node.switch.stop() node.peerManager.stop() - when defined(rln): - if not node.wakuRlnRelay.isNil(): - await node.wakuRlnRelay.stop() + if not node.wakuRlnRelay.isNil(): + await node.wakuRlnRelay.stop() node.started = false proc isReady*(node: WakuNode): Future[bool] {.async.} = - when defined(rln): - if node.wakuRlnRelay == nil: - return false - return await node.wakuRlnRelay.isReady() + if node.wakuRlnRelay == nil: + return true + return await node.wakuRlnRelay.isReady() ## TODO: add other protocol `isReady` checks - return true diff --git a/waku/waku_core/message/codec.nim b/waku/waku_core/message/codec.nim index 1e92535e7..51a260498 100644 --- a/waku/waku_core/message/codec.nim +++ b/waku/waku_core/message/codec.nim @@ -23,8 +23,7 @@ proc encode*(message: WakuMessage): ProtoBuffer = buf.write3(3, message.version) buf.write3(10, zint64(message.timestamp)) buf.write3(11, message.meta) - when defined(rln): - buf.write3(21, message.proof) + buf.write3(21, message.proof) buf.write3(31, message.ephemeral) buf.finish3() @@ -74,13 +73,12 @@ proc decode*(T: type WakuMessage, buffer: seq[byte]): ProtobufResult[T] = msg.meta = meta - # Experimental: this is part of https://rfc.vac.dev/spec/17/ spec - when defined(rln): - var proof: seq[byte] - if not ?pb.getField(21, proof): - msg.proof = @[] - else: - msg.proof = proof + # this is part of https://rfc.vac.dev/spec/17/ spec + var proof: seq[byte] + if not ?pb.getField(21, proof): + msg.proof = @[] + else: + msg.proof = proof var ephemeral: uint diff --git a/waku/waku_core/message/message.nim b/waku/waku_core/message/message.nim index d42c45a3a..fa79d7fcc 100644 --- a/waku/waku_core/message/message.nim +++ b/waku/waku_core/message/message.nim @@ -34,8 +34,7 @@ type WakuMessage* = object # The ephemeral attribute indicates signifies the transient nature of the # message (if the message should be stored). ephemeral*: bool - # EXPERIMENTAL: Part of RFC 17: https://rfc.vac.dev/spec/17/ - when defined(rln): - # The proof attribute indicates that the message is not a spam. This - # attribute will be used in the rln-relay protocol. - proof*: seq[byte] + # Part of RFC 17: https://rfc.vac.dev/spec/17/ + # The proof attribute indicates that the message is not spam. This + # attribute will be used in the rln-relay protocol. + proof*: seq[byte]