From 81edd57d7a26823ea816782e88e962cdd8347914 Mon Sep 17 00:00:00 2001 From: kdeme Date: Thu, 30 Apr 2020 17:51:30 +0200 Subject: [PATCH 1/9] Set up repo to make use of nimbus-build-system --- .gitignore | 22 +- .gitmodules | 100 ++++++++- LICENSE-APACHEv2 | 205 ++++++++++++++++++ LICENSE-MIT | 25 +++ Makefile | 106 +++++++-- config.nims | 57 +++++ env.sh | 8 + nim-waku.nimble | 11 - vendor/news | 1 + vendor/nim-bearssl | 1 + vendor/nim-chronicles | 1 + vendor/nim-chronos | 1 + vendor/nim-confutils | 1 + vendor/nim-faststreams | 1 + vendor/nim-http-utils | 1 + vendor/nim-json-rpc | 1 + vendor/nim-json-serialization | 1 + vendor/nim-libbacktrace | 1 + vendor/nim-metrics | 1 + vendor/nim-nat-traversal | 1 + vendor/nim-serialization | 1 + vendor/nim-stint | 1 + vendor/nimbus-build-system | 1 + vendor/nimcrypto | 1 + waku.nimble | 55 +++++ {node => waku/node}/README.md | 0 {node => waku/node}/v0/README.md | 0 {node => waku/node}/v0/config.nim | 0 {node => waku/node}/v0/docker/Dockerfile | 0 {node => waku/node}/v0/docker/Makefile | 0 .../v0/examples/waku-grafana-dashboard.json | 0 .../v0/metrics/prometheus/prometheus.yml | 0 .../waku-sim-all-nodes-grafana-dashboard.json | 0 {node => waku/node}/v0/nim.cfg | 0 {node => waku/node}/v0/quicksim.nim | 0 {node => waku/node}/v0/rpc/wakucallsigs.nim | 0 {node => waku/node}/v0/start_network.nim | 0 {node => waku/node}/v0/wakunode.nim | 0 {node => waku/node}/v2/README.md | 0 {node => waku/node}/v2/config.nim | 0 {node => waku/node}/v2/quicksim.nim | 0 {node => waku/node}/v2/rpc/wakucallsigs.nim | 0 {node => waku/node}/v2/rpc/wakurpc.nim | 0 {node => waku/node}/v2/wakunode.nim | 0 {protocol => waku/protocol}/README.md | 0 .../protocol}/v2/waku_protocol.nim | 0 46 files changed, 575 insertions(+), 30 deletions(-) create mode 100644 LICENSE-APACHEv2 create mode 100644 LICENSE-MIT create mode 100644 config.nims create mode 100755 env.sh delete mode 100644 nim-waku.nimble create mode 160000 vendor/news create mode 160000 vendor/nim-bearssl create mode 160000 vendor/nim-chronicles create mode 160000 vendor/nim-chronos create mode 160000 vendor/nim-confutils create mode 160000 vendor/nim-faststreams create mode 160000 vendor/nim-http-utils create mode 160000 vendor/nim-json-rpc create mode 160000 vendor/nim-json-serialization create mode 160000 vendor/nim-libbacktrace create mode 160000 vendor/nim-metrics create mode 160000 vendor/nim-nat-traversal create mode 160000 vendor/nim-serialization create mode 160000 vendor/nim-stint create mode 160000 vendor/nimbus-build-system create mode 160000 vendor/nimcrypto create mode 100644 waku.nimble rename {node => waku/node}/README.md (100%) rename {node => waku/node}/v0/README.md (100%) rename {node => waku/node}/v0/config.nim (100%) rename {node => waku/node}/v0/docker/Dockerfile (100%) rename {node => waku/node}/v0/docker/Makefile (100%) rename {node => waku/node}/v0/examples/waku-grafana-dashboard.json (100%) rename {node => waku/node}/v0/metrics/prometheus/prometheus.yml (100%) rename {node => waku/node}/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json (100%) rename {node => waku/node}/v0/nim.cfg (100%) rename {node => waku/node}/v0/quicksim.nim (100%) rename {node => waku/node}/v0/rpc/wakucallsigs.nim (100%) rename {node => waku/node}/v0/start_network.nim (100%) rename {node => waku/node}/v0/wakunode.nim (100%) rename {node => waku/node}/v2/README.md (100%) rename {node => waku/node}/v2/config.nim (100%) rename {node => waku/node}/v2/quicksim.nim (100%) rename {node => waku/node}/v2/rpc/wakucallsigs.nim (100%) rename {node => waku/node}/v2/rpc/wakurpc.nim (100%) rename {node => waku/node}/v2/wakunode.nim (100%) rename {protocol => waku/protocol}/README.md (100%) rename {protocol => waku/protocol}/v2/waku_protocol.nim (100%) diff --git a/.gitignore b/.gitignore index c795b054e..96e64b826 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,21 @@ -build \ No newline at end of file +/nimcache + +# Executables shall be put in an ignored build/ directory +/build + +# Nimble packages +/vendor/.nimble + +# ntags/ctags output +/tags + +# a symlink that can't be added to the repo because of Windows +/waku.nims + +# Ignore dynamic, static libs and libtool archive files +*.so +*.dylib +*.a +*.la +*.exe +*.dll diff --git a/.gitmodules b/.gitmodules index 9e68778b7..57049b412 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,105 @@ [submodule "vendor/nimbus"] path = vendor/nimbus - url = git@github.com:status-im/nimbus.git + url = https://github.com/status-im/nimbus.git + ignore = dirty + branch = master [submodule "vendor/nim-eth"] path = vendor/nim-eth - url = git@github.com:status-im/nim-eth.git + url = https://github.com/status-im/nim-eth.git + ignore = dirty + branch = master [submodule "vendor/nim-secp256k1"] path = vendor/nim-secp256k1 - url = git@github.com:status-im/nim-secp256k1.git + url = https://github.com/status-im/nim-secp256k1.git + ignore = dirty + branch = master [submodule "vendor/nim-libp2p"] path = vendor/nim-libp2p - url = git@github.com:status-im/nim-libp2p.git + url = https://github.com/status-im/nim-libp2p.git + ignore = dirty + branch = master [submodule "vendor/nim-stew"] path = vendor/nim-stew - url = git@github.com:status-im/nim-stew.git + url = https://github.com/status-im/nim-stew.git + ignore = dirty + branch = master +[submodule "vendor/nimbus-build-system"] + path = vendor/nimbus-build-system + url = https://github.com/status-im/nimbus-build-system.git + ignore = dirty + branch = master +[submodule "vendor/nim-nat-traversal"] + path = vendor/nim-nat-traversal + url = https://github.com/status-im/nim-nat-traversal.git + ignore = dirty + branch = master +[submodule "vendor/nim-libbacktrace"] + path = vendor/nim-libbacktrace + url = https://github.com/status-im/nim-libbacktrace.git + ignore = dirty + branch = master +[submodule "vendor/nim-confutils"] + path = vendor/nim-confutils + url = https://github.com/status-im/nim-confutils.git + ignore = dirty + branch = master +[submodule "vendor/nim-chronicles"] + path = vendor/nim-chronicles + url = https://github.com/status-im/nim-chronicles.git + ignore = dirty + branch = master +[submodule "vendor/nim-faststreams"] + path = vendor/nim-faststreams + url = https://github.com/status-im/nim-faststreams.git + ignore = dirty + branch = master +[submodule "vendor/nim-chronos"] + path = vendor/nim-chronos + url = https://github.com/status-im/nim-chronos.git + ignore = dirty + branch = master +[submodule "vendor/nim-json-serialization"] + path = vendor/nim-json-serialization + url = https://github.com/status-im/nim-json-serialization.git + ignore = dirty + branch = master +[submodule "vendor/nim-serialization"] + path = vendor/nim-serialization + url = https://github.com/status-im/nim-serialization.git + ignore = dirty + branch = master +[submodule "vendor/nimcrypto"] + path = vendor/nimcrypto + url = https://github.com/cheatfate/nimcrypto.git + ignore = dirty + branch = master +[submodule "vendor/nim-metrics"] + path = vendor/nim-metrics + url = https://github.com/status-im/nim-metrics.git + ignore = dirty + branch = master +[submodule "vendor/nim-stint"] + path = vendor/nim-stint + url = https://github.com/status-im/nim-stint.git + ignore = dirty + branch = master +[submodule "vendor/nim-json-rpc"] + path = vendor/nim-json-rpc + url = https://github.com/status-im/nim-json-rpc.git + ignore = dirty + branch = master +[submodule "vendor/nim-http-utils"] + path = vendor/nim-http-utils + url = https://github.com/status-im/nim-http-utils.git + ignore = dirty + branch = master +[submodule "vendor/news"] + path = vendor/news + url = https://github.com/tormund/news.git + ignore = dirty + branch = master +[submodule "vendor/nim-bearssl"] + path = vendor/nim-bearssl + url = https://github.com/status-im/nim-bearssl.git + ignore = dirty + branch = master diff --git a/LICENSE-APACHEv2 b/LICENSE-APACHEv2 new file mode 100644 index 000000000..81e878725 --- /dev/null +++ b/LICENSE-APACHEv2 @@ -0,0 +1,205 @@ +beacon_chain is licensed under the Apache License version 2 +Copyright (c) 2018 Status Research & Development GmbH +----------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Status Research & Development GmbH + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 000000000..4b6dda470 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +beacon_chain is licensed under the MIT License +Copyright (c) 2018 Status Research & Development GmbH +----------------------------------------------------- + +The MIT License (MIT) + +Copyright (c) 2018 Status Research & Development GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index e67c645a8..5da40826e 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,99 @@ -all: wakunode start_network quicksim +# Copyright (c) 2020 Status Research & Development GmbH. Licensed under +# either of: +# - Apache License, version 2.0 +# - MIT license +# at your option. This file may not be copied, modified, or distributed except +# according to those terms. -start_network: node/v0/start_network.nim - nim c --threads:on -o:build/start_network node/v0/start_network.nim +SHELL := bash # the shell used internally by Make -quicksim: node/v0/quicksim.nim - nim c --threads:on -o:build/quicksim node/v0/quicksim.nim +# used inside the included makefiles +BUILD_SYSTEM_DIR := vendor/nimbus-build-system -wakunode: node/v0/wakunode.nim - nim c --threads:on -o:build/wakunode node/v0/wakunode.nim +# we don't want an error here, so we can handle things later, in the ".DEFAULT" target +-include $(BUILD_SYSTEM_DIR)/makefiles/variables.mk -wakunode2: node/v2/wakunode.nim - nim c --threads:on -o:build/wakunode2 node/v2/wakunode.nim +.PHONY: \ + all \ + deps \ + update \ + wakunode \ + test \ + clean \ + libbacktrace -quicksim2: node/v2/quicksim.nim - nim c --threads:on -o:build/quicksim2 node/v2/quicksim.nim +ifeq ($(NIM_PARAMS),) +# "variables.mk" was not included, so we update the submodules. +GIT_SUBMODULE_UPDATE := git submodule update --init --recursive +.DEFAULT: + +@ echo -e "Git submodules not found. Running '$(GIT_SUBMODULE_UPDATE)'.\n"; \ + $(GIT_SUBMODULE_UPDATE); \ + echo +# Now that the included *.mk files appeared, and are newer than this file, Make will restart itself: +# https://www.gnu.org/software/make/manual/make.html#Remaking-Makefiles +# +# After restarting, it will execute its original goal, so we don't have to start a child Make here +# with "$(MAKE) $(MAKECMDGOALS)". Isn't hidden control flow great? -protocol2: protocol/v2/waku_protocol.nim - nim c --threads:on -o:build/protocol2 protocol/v2/waku_protocol.nim +else # "variables.mk" was included. Business as usual until the end of this file. + +# default target, because it's the first one that doesn't start with '.' +all: | wakunode + +# must be included after the default target +-include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk + +# "-d:release" implies "--stacktrace:off" and it cannot be added to config.nims +ifeq ($(USE_LIBBACKTRACE), 0) +NIM_PARAMS := $(NIM_PARAMS) -d:debug -d:disable_libbacktrace +else +NIM_PARAMS := $(NIM_PARAMS) -d:release +endif + +deps: | deps-common waku.nims +ifneq ($(USE_LIBBACKTRACE), 0) +deps: | libbacktrace +endif + +#- deletes and recreates "waku.nims" which on Windows is a copy instead of a proper symlink +update: | update-common + rm -rf waku.nims && \ + $(MAKE) waku.nims $(HANDLE_OUTPUT) + +# a phony target, because teaching `make` how to do conditional recompilation of Nim projects is too complicated +wakunode: | build deps + echo -e $(BUILD_MSG) "build/$@" && \ + $(ENV_SCRIPT) nim wakunode $(NIM_PARAMS) waku.nims + +wakusim: | build deps wakunode + echo -e $(BUILD_MSG) "build/$@" && \ + $(ENV_SCRIPT) nim wakusim $(NIM_PARAMS) waku.nims + +wakunode2: | build deps + echo -e $(BUILD_MSG) "build/$@" && \ + $(ENV_SCRIPT) nim wakunode2 $(NIM_PARAMS) waku.nims + +wakusim2: | build deps wakunode2 + echo -e $(BUILD_MSG) "build/$@" && \ + $(ENV_SCRIPT) nim wakusim2 $(NIM_PARAMS) waku.nims + +# symlink +waku.nims: + ln -s waku.nimble $@ + +# nim-libbacktrace +libbacktrace: + + $(MAKE) -C vendor/nim-libbacktrace --no-print-directory BUILD_CXX_LIB=0 + +# builds and runs the test suite +test: | build deps + $(ENV_SCRIPT) nim test $(NIM_PARAMS) waku.nims + +# usual cleaning +clean: | clean-common + rm -rf build/{wakunode,quicksim,start_network} +ifneq ($(USE_LIBBACKTRACE), 0) + + $(MAKE) -C vendor/nim-libbacktrace clean $(HANDLE_OUTPUT) +endif + +endif # "variables.mk" was not included diff --git a/config.nims b/config.nims new file mode 100644 index 000000000..1335d48d3 --- /dev/null +++ b/config.nims @@ -0,0 +1,57 @@ +if defined(release): + switch("nimcache", "nimcache/release/$projectName") +else: + switch("nimcache", "nimcache/debug/$projectName") + +if defined(windows): + # disable timestamps in Windows PE headers - https://wiki.debian.org/ReproducibleBuilds/TimestampsInPEBinaries + switch("passL", "-Wl,--no-insert-timestamp") + # increase stack size + switch("passL", "-Wl,--stack,8388608") + # https://github.com/nim-lang/Nim/issues/4057 + --tlsEmulation:off + if defined(i386): + # set the IMAGE_FILE_LARGE_ADDRESS_AWARE flag so we can use PAE, if enabled, and access more than 2 GiB of RAM + switch("passL", "-Wl,--large-address-aware") + + # The dynamic Chronicles output currently prevents us from using colors on Windows + # because these require direct manipulations of the stdout File object. + switch("define", "chronicles_colors=off") + +# This helps especially for 32-bit x86, which sans SSE2 and newer instructions +# requires quite roundabout code generation for cryptography, and other 64-bit +# and larger arithmetic use cases, along with register starvation issues. When +# engineering a more portable binary release, this should be tweaked but still +# use at least -msse2 or -msse3. +if defined(disableMarchNative): + switch("passC", "-msse3") +else: + switch("passC", "-march=native") + if defined(windows): + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65782 + # ("-fno-asynchronous-unwind-tables" breaks Nim's exception raising, sometimes) + switch("passC", "-mno-avx512vl") + +--threads:on +--opt:speed +--excessiveStackTrace:on +# enable metric collection +--define:metrics +# for heap-usage-by-instance-type metrics and object base-type strings +--define:nimTypeNames + +# the default open files limit is too low on macOS (512), breaking the +# "--debugger:native" build. It can be increased with `ulimit -n 1024`. +if not defined(macosx): + # add debugging symbols and original files and line numbers + --debugger:native + if not (defined(windows) and defined(i386)) and not defined(disable_libbacktrace): + # light-weight stack traces using libbacktrace and libunwind + --define:nimStackTraceOverride + switch("import", "libbacktrace") + +--define:nimOldCaseObjects # https://github.com/status-im/nim-confutils/issues/9 + +# `switch("warning[CaseTransition]", "off")` fails with "Error: invalid command line option: '--warning[CaseTransition]'" +switch("warning", "CaseTransition:off") + diff --git a/env.sh b/env.sh new file mode 100755 index 000000000..f90ba9a74 --- /dev/null +++ b/env.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# We use ${BASH_SOURCE[0]} instead of $0 to allow sourcing this file +# and we fall back to a Zsh-specific special var to also support Zsh. +REL_PATH="$(dirname ${BASH_SOURCE[0]:-${(%):-%x}})" +ABS_PATH="$(cd ${REL_PATH}; pwd)" +source ${ABS_PATH}/vendor/nimbus-build-system/scripts/env.sh + diff --git a/nim-waku.nimble b/nim-waku.nimble deleted file mode 100644 index 13483875a..000000000 --- a/nim-waku.nimble +++ /dev/null @@ -1,11 +0,0 @@ -# Package - -version = "0.1.0" -author = "Status Research & Development GmbH" -description = "Waku, Private P2P Messaging for Resource-Rerestricted Devices" -license = "MIT" -srcDir = "src" -#bin = @["build/waku"] - -# Dependencies -requires "nim >= 1.2.0" diff --git a/vendor/news b/vendor/news new file mode 160000 index 000000000..8ea2ee260 --- /dev/null +++ b/vendor/news @@ -0,0 +1 @@ +Subproject commit 8ea2ee260207c57a4b495931508569e181bb7b93 diff --git a/vendor/nim-bearssl b/vendor/nim-bearssl new file mode 160000 index 000000000..68c6d2730 --- /dev/null +++ b/vendor/nim-bearssl @@ -0,0 +1 @@ +Subproject commit 68c6d27304245c948526487b37e10951acf7dbc8 diff --git a/vendor/nim-chronicles b/vendor/nim-chronicles new file mode 160000 index 000000000..af184ae47 --- /dev/null +++ b/vendor/nim-chronicles @@ -0,0 +1 @@ +Subproject commit af184ae47e20672b68d20e7cacd3b726533548e1 diff --git a/vendor/nim-chronos b/vendor/nim-chronos new file mode 160000 index 000000000..357baa52a --- /dev/null +++ b/vendor/nim-chronos @@ -0,0 +1 @@ +Subproject commit 357baa52a0ea3da699c8229d97230c7f4340da92 diff --git a/vendor/nim-confutils b/vendor/nim-confutils new file mode 160000 index 000000000..6e5d57049 --- /dev/null +++ b/vendor/nim-confutils @@ -0,0 +1 @@ +Subproject commit 6e5d570490989c753d4645ba9173ef9358d302bb diff --git a/vendor/nim-faststreams b/vendor/nim-faststreams new file mode 160000 index 000000000..caab5c917 --- /dev/null +++ b/vendor/nim-faststreams @@ -0,0 +1 @@ +Subproject commit caab5c917ffd4a4c583dad9c59d2e1012eee9baa diff --git a/vendor/nim-http-utils b/vendor/nim-http-utils new file mode 160000 index 000000000..33d70b9f3 --- /dev/null +++ b/vendor/nim-http-utils @@ -0,0 +1 @@ +Subproject commit 33d70b9f378591e074838d6608a4468940137357 diff --git a/vendor/nim-json-rpc b/vendor/nim-json-rpc new file mode 160000 index 000000000..5c0d09611 --- /dev/null +++ b/vendor/nim-json-rpc @@ -0,0 +1 @@ +Subproject commit 5c0d0961114bcaaf3da52d5918bf0b85ef0e4ce9 diff --git a/vendor/nim-json-serialization b/vendor/nim-json-serialization new file mode 160000 index 000000000..cb695d175 --- /dev/null +++ b/vendor/nim-json-serialization @@ -0,0 +1 @@ +Subproject commit cb695d175fd809f6262f1ebc329e7c0b1d4505f5 diff --git a/vendor/nim-libbacktrace b/vendor/nim-libbacktrace new file mode 160000 index 000000000..fc63983c7 --- /dev/null +++ b/vendor/nim-libbacktrace @@ -0,0 +1 @@ +Subproject commit fc63983c73ba541413f12ee70a2b6f025b03efea diff --git a/vendor/nim-metrics b/vendor/nim-metrics new file mode 160000 index 000000000..65c91f1a7 --- /dev/null +++ b/vendor/nim-metrics @@ -0,0 +1 @@ +Subproject commit 65c91f1a7b5bf83968d0bebab74d14ddb6e9a432 diff --git a/vendor/nim-nat-traversal b/vendor/nim-nat-traversal new file mode 160000 index 000000000..2403c3392 --- /dev/null +++ b/vendor/nim-nat-traversal @@ -0,0 +1 @@ +Subproject commit 2403c33929c74f2d150f50dc8bc3a598af70661a diff --git a/vendor/nim-serialization b/vendor/nim-serialization new file mode 160000 index 000000000..9f085c33a --- /dev/null +++ b/vendor/nim-serialization @@ -0,0 +1 @@ +Subproject commit 9f085c33a9dc381bcf455225ccfad893b3d0361e diff --git a/vendor/nim-stint b/vendor/nim-stint new file mode 160000 index 000000000..9e49b0014 --- /dev/null +++ b/vendor/nim-stint @@ -0,0 +1 @@ +Subproject commit 9e49b00148884a01d61478ae5d2c69b543b93ceb diff --git a/vendor/nimbus-build-system b/vendor/nimbus-build-system new file mode 160000 index 000000000..e8e1f1c2c --- /dev/null +++ b/vendor/nimbus-build-system @@ -0,0 +1 @@ +Subproject commit e8e1f1c2cff5aebf74dff07b1cf119134267922b diff --git a/vendor/nimcrypto b/vendor/nimcrypto new file mode 160000 index 000000000..30d0ceaba --- /dev/null +++ b/vendor/nimcrypto @@ -0,0 +1 @@ +Subproject commit 30d0ceaba02c0b966515f98873a0404786fbf796 diff --git a/waku.nimble b/waku.nimble new file mode 100644 index 000000000..70c6eb6a6 --- /dev/null +++ b/waku.nimble @@ -0,0 +1,55 @@ +mode = ScriptMode.Verbose + +### Package +version = "0.1.0" +author = "Status Research & Development GmbH" +description = "Waku, Private P2P Messaging for Resource-Rerestricted Devices" +license = "MIT or Apache License 2.0" +srcDir = "src" +#bin = @["build/waku"] + +### Dependencies +requires "nim >= 1.2.0", + "chronicles", + "confutils", + "chronos", + "eth", + "json_rpc", + "libbacktrace", + "nimcrypto", + "stew", + "stint", + "metrics", + "libp2p" # For wakunode v2 + +### Helper functions +proc buildBinary(name: string, srcDir = "./", params = "", lang = "c") = + if not dirExists "build": + mkDir "build" + # allow something like "nim nimbus --verbosity:0 --hints:off nimbus.nims" + var extra_params = params + for i in 2.. Date: Thu, 30 Apr 2020 18:07:02 +0200 Subject: [PATCH 2/9] Update waku/node with latest of waku files in nimbus repository --- waku/node/v0/README.md | 19 +- .../node/v0/metrics/prometheus/prometheus.yml | 28 +- .../waku-sim-all-nodes-grafana-dashboard.json | 6088 ----------------- 3 files changed, 14 insertions(+), 6121 deletions(-) diff --git a/waku/node/v0/README.md b/waku/node/v0/README.md index d654e5cde..c73e1b66f 100644 --- a/waku/node/v0/README.md +++ b/waku/node/v0/README.md @@ -1,8 +1,9 @@ # Introduction `wakunode` is a cli application that allows you to run a -[Waku](https://github.com/vacp2p/specs/blob/master/waku.md) enabled node. +[Waku](https://specs.vac.dev/waku/waku.html) enabled node. -The application and Waku specification are still experimental and fully in flux. +The Waku specification is still in draft and thus this implementation will +change accordingly. Additionally the original Whisper (EIP-627) protocol can also be enabled as can an experimental Whisper - Waku bridging option. @@ -19,11 +20,15 @@ More information on the installation of these can be found [here](https://github ## Build & Run ```bash -make # The first `make` invocation will update all Git submodules and prompt you to run `make` again. - # It's only required once per Git clone. You'll run `make update` after each `git pull`, in the future, - # to keep those submodules up to date. +# The first `make` invocation will update all Git submodules. +# You'll run `make update` after each `git pull`, in the future, to keep those submodules up to date. make wakunode + +# See available command line options ./build/wakunode --help + +# Connect the client directly with the Status test fleet +./build/wakunode --log-level:debug --discovery:off --fleet:test --log-metrics ``` # Using Metrics @@ -87,9 +92,9 @@ This dashboard can be found at `./waku/metrics/waku-sim-all-nodes-grafana-dashbo # Spec support -*This section last updated April 7, 2020* +*This section last updated April 21, 2020* -This client of Waku is spec compliant with [Waku spec v0.4](https://specs.vac.dev/waku/waku.html). +This client of Waku is spec compliant with [Waku spec v1.0](https://specs.vac.dev/waku/waku.html). It doesn't yet implement the following recommended features: - No support for rate limiting diff --git a/waku/node/v0/metrics/prometheus/prometheus.yml b/waku/node/v0/metrics/prometheus/prometheus.yml index fd4f53f83..055734cfa 100644 --- a/waku/node/v0/metrics/prometheus/prometheus.yml +++ b/waku/node/v0/metrics/prometheus/prometheus.yml @@ -16,33 +16,9 @@ - targets: ['127.0.0.1:8013'] labels: node: '3' - - targets: ['127.0.0.1:8014'] - labels: - node: '4' - - targets: ['127.0.0.1:8015'] - labels: - node: '5' - - targets: ['127.0.0.1:8016'] - labels: - node: '6' - - targets: ['127.0.0.1:8017'] - labels: - node: '7' - - targets: ['127.0.0.1:8018'] - labels: - node: '8' - - targets: ['127.0.0.1:8019'] - labels: - node: '9' - - targets: ['127.0.0.1:8020'] - labels: - node: '10' - - targets: ['127.0.0.1:8021'] - labels: - node: '11' - targets: ['127.0.0.1:8008'] labels: - node: '12' + node: '4' - targets: ['127.0.0.1:8009'] labels: - node: '13' \ No newline at end of file + node: '5' \ No newline at end of file diff --git a/waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json b/waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json index 44f34d70b..145f4469b 100644 --- a/waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json +++ b/waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json @@ -4583,6094 +4583,6 @@ "align": false, "alignLevel": null } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 126 - }, - "id": 54, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"6\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #6", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 126 - }, - "id": 55, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"6\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #6", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 126 - }, - "id": 56, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"6\"} + dropped_from_future_envelopes_total{node=\"6\"} + dropped_low_pow_envelopes_total{node=\"6\"} + dropped_too_large_envelopes_total{node=\"6\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"6\"} + dropped_topic_mismatch_envelopes_total{node=\"6\"} +dropped_benign_duplicate_envelopes_total{node=\"6\"} + dropped_duplicate_envelopes_total{node=\"6\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #6", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 126 - }, - "id": 57, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"6\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #6", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 126 - }, - "id": 58, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"6\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #6", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 130 - }, - "id": 59, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"6\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"6\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"6\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #6", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 130 - }, - "id": 60, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"6\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"6\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"6\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #6", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 139 - }, - "id": 61, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"6\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"6\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #6", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 139 - }, - "id": 62, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"6\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"6\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"6\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"6\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #6", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 147 - }, - "id": 63, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"7\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #7", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 147 - }, - "id": 64, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"7\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #7", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 147 - }, - "id": 65, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"7\"} + dropped_from_future_envelopes_total{node=\"7\"} + dropped_low_pow_envelopes_total{node=\"7\"} + dropped_too_large_envelopes_total{node=\"7\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"7\"} + dropped_topic_mismatch_envelopes_total{node=\"7\"} +dropped_benign_duplicate_envelopes_total{node=\"7\"} + dropped_duplicate_envelopes_total{node=\"7\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #7", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 147 - }, - "id": 66, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"7\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #7", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 147 - }, - "id": 67, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"7\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #7", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 151 - }, - "id": 68, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"7\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"7\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"7\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #7", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 151 - }, - "id": 69, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"7\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"7\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"7\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #7", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 160 - }, - "id": 70, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"7\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"7\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #7", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 160 - }, - "id": 71, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"7\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"7\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"7\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"7\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #7", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 168 - }, - "id": 72, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"8\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #8", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 168 - }, - "id": 73, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"8\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #8", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 168 - }, - "id": 74, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"8\"} + dropped_from_future_envelopes_total{node=\"8\"} + dropped_low_pow_envelopes_total{node=\"8\"} + dropped_too_large_envelopes_total{node=\"8\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"8\"} + dropped_topic_mismatch_envelopes_total{node=\"8\"} +dropped_benign_duplicate_envelopes_total{node=\"8\"} + dropped_duplicate_envelopes_total{node=\"8\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #8", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 168 - }, - "id": 75, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"8\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #8", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 168 - }, - "id": 76, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"8\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #8", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 172 - }, - "id": 77, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"8\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"8\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"8\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #8", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 172 - }, - "id": 78, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"8\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"8\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"8\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #8", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 181 - }, - "id": 79, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"8\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"8\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #8", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 181 - }, - "id": 80, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"8\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"8\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"8\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"8\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #8", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 189 - }, - "id": 81, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"9\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #9", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 189 - }, - "id": 82, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"9\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #9", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 189 - }, - "id": 83, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"9\"} + dropped_from_future_envelopes_total{node=\"9\"} + dropped_low_pow_envelopes_total{node=\"9\"} + dropped_too_large_envelopes_total{node=\"9\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"9\"} + dropped_topic_mismatch_envelopes_total{node=\"9\"} +dropped_benign_duplicate_envelopes_total{node=\"9\"} + dropped_duplicate_envelopes_total{node=\"9\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #9", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 189 - }, - "id": 84, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"9\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #9", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 189 - }, - "id": 85, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"9\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #9", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 193 - }, - "id": 86, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"9\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"9\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"9\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #9", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 193 - }, - "id": 87, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"9\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"9\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"9\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #9", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 202 - }, - "id": 88, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"9\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"9\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #9", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 202 - }, - "id": 89, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"9\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"9\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"9\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"9\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #9", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 210 - }, - "id": 90, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"10\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #10", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 210 - }, - "id": 91, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"10\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #10", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 210 - }, - "id": 92, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"10\"} + dropped_from_future_envelopes_total{node=\"10\"} + dropped_low_pow_envelopes_total{node=\"10\"} + dropped_too_large_envelopes_total{node=\"10\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"10\"} + dropped_topic_mismatch_envelopes_total{node=\"10\"} +dropped_benign_duplicate_envelopes_total{node=\"10\"} + dropped_duplicate_envelopes_total{node=\"10\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #10", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 210 - }, - "id": 93, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"10\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #10", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 210 - }, - "id": 94, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"10\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #10", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 214 - }, - "id": 95, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"10\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"10\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"10\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #10", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 214 - }, - "id": 96, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"10\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"10\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"10\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #10", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 223 - }, - "id": 97, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"10\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"10\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #10", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 223 - }, - "id": 98, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"10\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"10\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"10\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"10\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #10", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 231 - }, - "id": 99, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"11\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #11", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 231 - }, - "id": 100, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"11\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #11", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 231 - }, - "id": 101, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"11\"} + dropped_from_future_envelopes_total{node=\"11\"} + dropped_low_pow_envelopes_total{node=\"11\"} + dropped_too_large_envelopes_total{node=\"11\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"11\"} + dropped_topic_mismatch_envelopes_total{node=\"11\"} +dropped_benign_duplicate_envelopes_total{node=\"11\"} + dropped_duplicate_envelopes_total{node=\"11\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #11", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 231 - }, - "id": 102, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"11\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #11", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 231 - }, - "id": 103, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"11\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #11", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 235 - }, - "id": 104, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"11\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"11\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"11\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #11", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 235 - }, - "id": 105, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"11\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"11\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"11\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #11", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 244 - }, - "id": 106, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"11\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"11\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #11", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 244 - }, - "id": 107, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"11\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"11\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"11\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"11\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #11", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 252 - }, - "id": 108, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"12\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #12", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 252 - }, - "id": 109, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"12\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #12", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 252 - }, - "id": 110, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"12\"} + dropped_from_future_envelopes_total{node=\"12\"} + dropped_low_pow_envelopes_total{node=\"12\"} + dropped_too_large_envelopes_total{node=\"12\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"12\"} + dropped_topic_mismatch_envelopes_total{node=\"12\"} +dropped_benign_duplicate_envelopes_total{node=\"12\"} + dropped_duplicate_envelopes_total{node=\"12\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #12", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 252 - }, - "id": 111, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"12\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #12", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 252 - }, - "id": 112, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"12\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #12", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 256 - }, - "id": 113, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"12\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"12\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"12\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #12", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 256 - }, - "id": 114, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"12\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"12\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"12\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #12", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 265 - }, - "id": 115, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"12\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"12\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #12", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 265 - }, - "id": 116, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"12\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"12\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"12\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"12\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #12", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 273 - }, - "id": 117, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "connected_peers{node=\"13\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Connected Peers #13", - "type": "gauge" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 6, - "y": 273 - }, - "id": 118, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "valid_envelopes_total{node=\"13\"}", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Valid Envelopes #13", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 10, - "y": 273 - }, - "id": 119, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "pluginVersion": "6.4.5", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "dropped_expired_envelopes_total{node=\"13\"} + dropped_from_future_envelopes_total{node=\"13\"} + dropped_low_pow_envelopes_total{node=\"13\"} + dropped_too_large_envelopes_total{node=\"13\"} + dropped_bloom_filter_mismatch_envelopes_total{node=\"13\"} + dropped_topic_mismatch_envelopes_total{node=\"13\"} +dropped_benign_duplicate_envelopes_total{node=\"13\"} + dropped_duplicate_envelopes_total{node=\"13\"}", - "legendFormat": "Invalid envelopes", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Invalid Envelopes #13", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 14, - "y": 273 - }, - "id": 120, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 200 - } - ], - "unit": "percent" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{node=\"13\"}[5s]) * 100", - "legendFormat": "CPU Usage", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage #13", - "type": "gauge" - }, - { - "datasource": null, - "gridPos": { - "h": 4, - "w": 5, - "x": 19, - "y": 273 - }, - "id": 121, - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [], - "max": 2147483648, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 2147483648 - } - ], - "unit": "bytes" - }, - "override": {}, - "values": false - }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.4.5", - "targets": [ - { - "expr": "process_resident_memory_bytes{node=\"13\"}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "RSS Memory #13", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 277 - }, - "id": 122, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pluginVersion": "6.4.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "valid_envelopes_total{node=\"13\"}", - "hide": false, - "instant": false, - "legendFormat": "Valid", - "refId": "A" - }, - { - "expr": "dropped_benign_duplicate_envelopes_total{node=\"13\"}", - "hide": false, - "instant": false, - "legendFormat": "Benign duplicate", - "refId": "B" - }, - { - "expr": "dropped_duplicate_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Duplicate", - "refId": "C" - }, - { - "expr": "dropped_expired_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Expired", - "refId": "D" - }, - { - "expr": "dropped_from_future_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Future timestamped", - "refId": "E" - }, - { - "expr": "dropped_low_pow_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Too low PoW", - "refId": "F" - }, - { - "expr": "dropped_bloom_filter_mismatch_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Bloom filter mismatch", - "refId": "G" - }, - { - "expr": "dropped_topic_mismatch_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Topic mismatch", - "refId": "H" - }, - { - "expr": "dropped_too_large_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Too Large", - "refId": "I" - }, - { - "expr": "dropped_full_queue_new_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Full queue new", - "refId": "J" - }, - { - "expr": "dropped_full_queue_old_envelopes_total{node=\"13\"}", - "hide": false, - "legendFormat": "Full queue old", - "refId": "K" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Envelopes #13", - "tooltip": { - "shared": true, - "sort": 1, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 277 - }, - "id": 123, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "RSS Memory", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "connected_peers{node=\"13\"}", - "intervalFactor": 1, - "legendFormat": "Connected Peers", - "refId": "A" - }, - { - "expr": "process_resident_memory_bytes{node=\"13\"}", - "interval": "", - "intervalFactor": 1, - "legendFormat": "RSS Memory", - "refId": "B" - }, - { - "expr": "rate(process_cpu_seconds_total{node=\"13\"}[15s]) * 100", - "legendFormat": "CPU usage %", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Waku Node #13", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 286 - }, - "id": 124, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_max_fds{node=\"13\"}", - "legendFormat": "Maximum file descriptors", - "refId": "A" - }, - { - "expr": "process_open_fds{node=\"13\"}", - "legendFormat": "Open file descriptors", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "File Descriptors #13", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 286 - }, - "id": 125, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nim_gc_mem_bytes{node=\"13\"}", - "legendFormat": "Nim GC total memory", - "refId": "A" - }, - { - "expr": "nim_gc_mem_occupied_bytes{node=\"13\"}", - "legendFormat": "Nim GC used memory", - "refId": "B" - }, - { - "expr": "process_resident_memory_bytes{node=\"13\"}", - "legendFormat": "RSS memory", - "refId": "C" - }, - { - "expr": "process_virtual_memory_bytes{node=\"13\"}", - "legendFormat": "Virtual memory", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage #13", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } } ], "refresh": "5s", From c313c8fcbfab0c0e2354f2d023036132e561ce63 Mon Sep 17 00:00:00 2001 From: kdeme Date: Thu, 30 Apr 2020 22:35:57 +0200 Subject: [PATCH 3/9] Move Nimbus Waku RPC code + add converted whisper rpc test - Move Waku RPC code from Nimbus + necessary code around it - Add Waku RPC test which is a copy of the Whisper RPC test - Some renaming - Remove nimbus submodule --- .gitmodules | 5 - Makefile | 2 +- tests/all_tests.nim | 2 + tests/test_rpc_waku.nim | 238 ++++++++++++++++++++ vendor/nimbus | 1 - waku.nimble | 3 +- waku/node/v0/config.nim | 3 +- waku/node/v0/quicksim.nim | 8 +- waku/node/v0/rpc/hexstrings.nim | 225 ++++++++++++++++++ waku/node/v0/rpc/key_storage.nim | 22 ++ waku/node/v0/rpc/rpc_types.nim | 58 +++++ waku/node/v0/rpc/waku.nim | 363 ++++++++++++++++++++++++++++++ waku/node/v0/rpc/wakucallsigs.nim | 8 +- waku/node/v0/rpc/wakusim.nim | 31 +++ waku/node/v0/wakunode.nim | 2 +- 15 files changed, 951 insertions(+), 20 deletions(-) create mode 100644 tests/all_tests.nim create mode 100644 tests/test_rpc_waku.nim delete mode 160000 vendor/nimbus create mode 100644 waku/node/v0/rpc/hexstrings.nim create mode 100644 waku/node/v0/rpc/key_storage.nim create mode 100644 waku/node/v0/rpc/rpc_types.nim create mode 100644 waku/node/v0/rpc/waku.nim create mode 100644 waku/node/v0/rpc/wakusim.nim diff --git a/.gitmodules b/.gitmodules index 57049b412..16ff5ddfb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,8 +1,3 @@ -[submodule "vendor/nimbus"] - path = vendor/nimbus - url = https://github.com/status-im/nimbus.git - ignore = dirty - branch = master [submodule "vendor/nim-eth"] path = vendor/nim-eth url = https://github.com/status-im/nim-eth.git diff --git a/Makefile b/Makefile index 5da40826e..333557f04 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ test: | build deps # usual cleaning clean: | clean-common - rm -rf build/{wakunode,quicksim,start_network} + rm -rf build/{wakunode,quicksim,start_network,all_tests} ifneq ($(USE_LIBBACKTRACE), 0) + $(MAKE) -C vendor/nim-libbacktrace clean $(HANDLE_OUTPUT) endif diff --git a/tests/all_tests.nim b/tests/all_tests.nim new file mode 100644 index 000000000..1948456c2 --- /dev/null +++ b/tests/all_tests.nim @@ -0,0 +1,2 @@ +import + ./test_rpc_waku \ No newline at end of file diff --git a/tests/test_rpc_waku.nim b/tests/test_rpc_waku.nim new file mode 100644 index 000000000..eb8e26049 --- /dev/null +++ b/tests/test_rpc_waku.nim @@ -0,0 +1,238 @@ +import + unittest, strformat, options, stew/byteutils, json_rpc/[rpcserver, rpcclient], + eth/common as eth_common, eth/[rlp, keys, p2p], + eth/p2p/rlpx_protocols/waku_protocol, + ../waku/node/v0/rpc/[hexstrings, rpc_types, waku, key_storage] + +from os import DirSep, ParDir +from strutils import rsplit +template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0] + +## Generate client convenience marshalling wrappers from forward declarations +## For testing, ethcallsigs needs to be kept in sync with ../waku/node/v0/rpc/waku +const sigPath = &"{sourceDir}{DirSep}{ParDir}{DirSep}waku{DirSep}node{DirSep}v0{DirSep}rpc{DirSep}wakucallsigs.nim" +createRpcSigs(RpcSocketClient, sigPath) + +proc setupNode(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = + let + keypair = KeyPair.random()[] + srvAddress = Address(ip: parseIpAddress("0.0.0.0"), tcpPort: Port(30303), + udpPort: Port(30303)) + + result = newEthereumNode(keypair, srvAddress, 1, nil, "waku test rpc", + addAllCapabilities = false) + for capability in capabilities: + result.addCapability capability + +proc doTests {.async.} = + var ethNode = setupNode(Waku) + + # Create Ethereum RPCs + let rpcPort = 8545 + var + rpcServer = newRpcSocketServer(["localhost:" & $rpcPort]) + client = newRpcSocketClient() + let keys = newKeyStorage() + setupWakuRPC(ethNode, keys, rpcServer) + + # Begin tests + rpcServer.start() + await client.connect("localhost", Port(rpcPort)) + + suite "Waku Remote Procedure Calls": + test "waku_version": + check await(client.waku_version()) == wakuVersionStr + test "waku_info": + let info = await client.waku_info() + check info.maxMessageSize == defaultMaxMsgSize + test "waku_setMaxMessageSize": + let testValue = 1024'u64 + check await(client.waku_setMaxMessageSize(testValue)) == true + var info = await client.waku_info() + check info.maxMessageSize == testValue + expect ValueError: + discard await(client.waku_setMaxMessageSize(defaultMaxMsgSize + 1)) + info = await client.waku_info() + check info.maxMessageSize == testValue + test "waku_setMinPoW": + let testValue = 0.0001 + check await(client.waku_setMinPoW(testValue)) == true + let info = await client.waku_info() + check info.minPow == testValue + # test "waku_markTrustedPeer": + # TODO: need to connect a peer to test + test "waku asymKey tests": + let keyID = await client.waku_newKeyPair() + check: + await(client.waku_hasKeyPair(keyID)) == true + await(client.waku_deleteKeyPair(keyID)) == true + await(client.waku_hasKeyPair(keyID)) == false + expect ValueError: + discard await(client.waku_deleteKeyPair(keyID)) + + let privkey = "0x5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3" + let pubkey = "0x04e5fd642a0f630bbb1e4cd7df629d7b8b019457a9a74f983c0484a045cebb176def86a54185b50bbba6bbf97779173695e92835d63109c23471e6da382f922fdb" + let keyID2 = await client.waku_addPrivateKey(privkey) + check: + await(client.waku_getPublicKey(keyID2)) == pubkey.toPublicKey + await(client.waku_getPrivateKey(keyID2)).toRaw() == privkey.toPrivateKey.toRaw() + await(client.waku_hasKeyPair(keyID2)) == true + await(client.waku_deleteKeyPair(keyID2)) == true + await(client.waku_hasKeyPair(keyID2)) == false + expect ValueError: + discard await(client.waku_deleteKeyPair(keyID2)) + test "waku symKey tests": + let keyID = await client.waku_newSymKey() + check: + await(client.waku_hasSymKey(keyID)) == true + await(client.waku_deleteSymKey(keyID)) == true + await(client.waku_hasSymKey(keyID)) == false + expect ValueError: + discard await(client.waku_deleteSymKey(keyID)) + + let symKey = "0x0000000000000000000000000000000000000000000000000000000000000001" + let keyID2 = await client.waku_addSymKey(symKey) + check: + await(client.waku_getSymKey(keyID2)) == symKey.toSymKey + await(client.waku_hasSymKey(keyID2)) == true + await(client.waku_deleteSymKey(keyID2)) == true + await(client.waku_hasSymKey(keyID2)) == false + expect ValueError: + discard await(client.waku_deleteSymKey(keyID2)) + + let keyID3 = await client.waku_generateSymKeyFromPassword("password") + let keyID4 = await client.waku_generateSymKeyFromPassword("password") + let keyID5 = await client.waku_generateSymKeyFromPassword("nimbus!") + check: + await(client.waku_getSymKey(keyID3)) == + await(client.waku_getSymKey(keyID4)) + await(client.waku_getSymKey(keyID3)) != + await(client.waku_getSymKey(keyID5)) + await(client.waku_hasSymKey(keyID3)) == true + await(client.waku_deleteSymKey(keyID3)) == true + await(client.waku_hasSymKey(keyID3)) == false + expect ValueError: + discard await(client.waku_deleteSymKey(keyID3)) + + # Some defaults for the filter & post tests + let + ttl = 30'u64 + topicStr = "0x12345678" + payload = "0x45879632" + # A very low target and long time so we are sure the test never fails + # because of this + powTarget = 0.001 + powTime = 1.0 + + test "waku filter create and delete": + let + topic = topicStr.toTopic() + symKeyID = await client.waku_newSymKey() + options = WakuFilterOptions(symKeyID: some(symKeyID), + topics: some(@[topic])) + filterID = await client.waku_newMessageFilter(options) + + check: + filterID.string.isValidIdentifier + await(client.waku_deleteMessageFilter(filterID)) == true + expect ValueError: + discard await(client.waku_deleteMessageFilter(filterID)) + + test "waku symKey post and filter loop": + let + topic = topicStr.toTopic() + symKeyID = await client.waku_newSymKey() + options = WakuFilterOptions(symKeyID: some(symKeyID), + topics: some(@[topic])) + filterID = await client.waku_newMessageFilter(options) + message = WakuPostMessage(symKeyID: some(symKeyID), + ttl: ttl, + topic: some(topic), + payload: payload.HexDataStr, + powTime: powTime, + powTarget: powTarget) + check: + await(client.waku_setMinPoW(powTarget)) == true + await(client.waku_post(message)) == true + + let messages = await client.waku_getFilterMessages(filterID) + check: + messages.len == 1 + messages[0].sig.isNone() + messages[0].recipientPublicKey.isNone() + messages[0].ttl == ttl + messages[0].topic == topic + messages[0].payload == hexToSeqByte(payload) + messages[0].padding.len > 0 + messages[0].pow >= powTarget + + await(client.waku_deleteMessageFilter(filterID)) == true + + test "waku asymKey post and filter loop": + let + topic = topicStr.toTopic() + privateKeyID = await client.waku_newKeyPair() + options = WakuFilterOptions(privateKeyID: some(privateKeyID)) + filterID = await client.waku_newMessageFilter(options) + pubKey = await client.waku_getPublicKey(privateKeyID) + message = WakuPostMessage(pubKey: some(pubKey), + ttl: ttl, + topic: some(topic), + payload: payload.HexDataStr, + powTime: powTime, + powTarget: powTarget) + check: + await(client.waku_setMinPoW(powTarget)) == true + await(client.waku_post(message)) == true + + let messages = await client.waku_getFilterMessages(filterID) + check: + messages.len == 1 + messages[0].sig.isNone() + messages[0].recipientPublicKey.get() == pubKey + messages[0].ttl == ttl + messages[0].topic == topic + messages[0].payload == hexToSeqByte(payload) + messages[0].padding.len > 0 + messages[0].pow >= powTarget + + await(client.waku_deleteMessageFilter(filterID)) == true + + test "waku signature in post and filter loop": + let + topic = topicStr.toTopic() + symKeyID = await client.waku_newSymKey() + privateKeyID = await client.waku_newKeyPair() + pubKey = await client.waku_getPublicKey(privateKeyID) + options = WakuFilterOptions(symKeyID: some(symKeyID), + topics: some(@[topic]), + sig: some(pubKey)) + filterID = await client.waku_newMessageFilter(options) + message = WakuPostMessage(symKeyID: some(symKeyID), + sig: some(privateKeyID), + ttl: ttl, + topic: some(topic), + payload: payload.HexDataStr, + powTime: powTime, + powTarget: powTarget) + check: + await(client.waku_setMinPoW(powTarget)) == true + await(client.waku_post(message)) == true + + let messages = await client.waku_getFilterMessages(filterID) + check: + messages.len == 1 + messages[0].sig.get() == pubKey + messages[0].recipientPublicKey.isNone() + messages[0].ttl == ttl + messages[0].topic == topic + messages[0].payload == hexToSeqByte(payload) + messages[0].padding.len > 0 + messages[0].pow >= powTarget + + await(client.waku_deleteMessageFilter(filterID)) == true + + rpcServer.stop() + rpcServer.close() + +waitFor doTests() diff --git a/vendor/nimbus b/vendor/nimbus deleted file mode 160000 index ff028982d..000000000 --- a/vendor/nimbus +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ff028982d6fc414c17d98d4c5e6d6d3856c0c598 diff --git a/waku.nimble b/waku.nimble index 70c6eb6a6..e5a4df73b 100644 --- a/waku.nimble +++ b/waku.nimble @@ -38,8 +38,7 @@ proc test(name: string, lang = "c") = ### Tasks task test, "Run tests": - discard -# test "all_tests" + test "all_tests" task wakunode, "Build Waku cli": buildBinary "wakunode", "waku/node/v0/", "-d:chronicles_log_level=TRACE" diff --git a/waku/node/v0/config.nim b/waku/node/v0/config.nim index 688c4ff31..3ce11d157 100644 --- a/waku/node/v0/config.nim +++ b/waku/node/v0/config.nim @@ -1,6 +1,5 @@ import - confutils/defs, chronicles, chronos, - eth/keys, eth/p2p/rlpx_protocols/waku_protocol + confutils/defs, chronicles, chronos, eth/keys type Fleet* = enum diff --git a/waku/node/v0/quicksim.nim b/waku/node/v0/quicksim.nim index 2abf2089b..200bc5200 100644 --- a/waku/node/v0/quicksim.nim +++ b/waku/node/v0/quicksim.nim @@ -1,7 +1,7 @@ import os, strformat, chronicles, json_rpc/[rpcclient, rpcserver], nimcrypto/sysrand, eth/common as eth_common, eth/keys, eth/p2p/rlpx_protocols/waku_protocol, - ../../vendor/nimbus/nimbus/rpc/[hexstrings, rpc_types, waku], + ./rpc/[hexstrings, rpc_types], options as what # TODO: Huh? Redefinition? from os import DirSep @@ -33,18 +33,18 @@ let symKey = "0x0000000000000000000000000000000000000000000000000000000000000001" topics = generateTopics() symKeyID = waitFor lightNode.waku_addSymKey(symKey) - options = WhisperFilterOptions(symKeyID: some(symKeyID), + options = WakuFilterOptions(symKeyID: some(symKeyID), topics: some(topics)) filterID = waitFor lightNode.waku_newMessageFilter(options) symKeyID2 = waitFor lightNode2.waku_addSymKey(symKey) - options2 = WhisperFilterOptions(symKeyID: some(symKeyID2), + options2 = WakuFilterOptions(symKeyID: some(symKeyID2), topics: some(topics)) filterID2 = waitFor lightNode2.waku_newMessageFilter(options2) symkeyID3 = waitFor trafficNode.waku_addSymKey(symKey) -var message = WhisperPostMessage(symKeyID: some(symkeyID3), +var message = WakuPostMessage(symKeyID: some(symkeyID3), ttl: 30, topic: some(topics[0]), payload: "0x45879632".HexDataStr, diff --git a/waku/node/v0/rpc/hexstrings.nim b/waku/node/v0/rpc/hexstrings.nim new file mode 100644 index 000000000..d5051996e --- /dev/null +++ b/waku/node/v0/rpc/hexstrings.nim @@ -0,0 +1,225 @@ +# Nimbus +# Copyright (c) 2018 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +## This module implements the Ethereum hexadecimal string formats for JSON +## See: https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding + +#[ + Note: + The following types are converted to hex strings when marshalled to JSON: + * Hash256 + * UInt256 + * seq[byte] + * openArray[seq] + * PublicKey + * PrivateKey + * SymKey + * Topic + * Bytes +]# + +import + stint, stew/byteutils, eth/[keys, rlp], eth/common/eth_types, + eth/p2p/rlpx_protocols/waku_protocol + +type + HexDataStr* = distinct string + Identifier* = distinct string # 32 bytes, no 0x prefix! + HexStrings = HexDataStr | Identifier + +# Hex validation + +template hasHexHeader(value: string): bool = + if value.len >= 2 and value[0] == '0' and value[1] in {'x', 'X'}: true + else: false + +template isHexChar(c: char): bool = + if c notin {'0'..'9'} and + c notin {'a'..'f'} and + c notin {'A'..'F'}: false + else: true + +func isValidHexQuantity*(value: string): bool = + if not value.hasHexHeader: + return false + # No leading zeros (but allow 0x0) + if value.len < 3 or (value.len > 3 and value[2] == '0'): return false + for i in 2 ..< value.len: + let c = value[i] + if not c.isHexChar: + return false + return true + +func isValidHexData*(value: string, header = true): bool = + if header and not value.hasHexHeader: + return false + # Must be even number of digits + if value.len mod 2 != 0: return false + # Leading zeros are allowed + for i in 2 ..< value.len: + let c = value[i] + if not c.isHexChar: + return false + return true + +template isValidHexData(value: string, hexLen: int, header = true): bool = + value.len == hexLen and value.isValidHexData(header) + +func isValidIdentifier*(value: string): bool = + # 32 bytes for Whisper ID, no 0x prefix + result = value.isValidHexData(64, false) + +func isValidPublicKey*(value: string): bool = + # 65 bytes for Public Key plus 1 byte for 0x prefix + result = value.isValidHexData(132) + +func isValidPrivateKey*(value: string): bool = + # 32 bytes for Private Key plus 1 byte for 0x prefix + result = value.isValidHexData(66) + +func isValidSymKey*(value: string): bool = + # 32 bytes for Private Key plus 1 byte for 0x prefix + result = value.isValidHexData(66) + +func isValidHash256*(value: string): bool = + # 32 bytes for Hash256 plus 1 byte for 0x prefix + result = value.isValidHexData(66) + +func isValidTopic*(value: string): bool = + # 4 bytes for Topic plus 1 byte for 0x prefix + result = value.isValidHexData(10) + +const + SInvalidData = "Invalid hex data format for Ethereum" + +proc validateHexData*(value: string) {.inline.} = + if unlikely(not value.isValidHexData): + raise newException(ValueError, SInvalidData & ": " & value) + +# Initialisation + +proc hexDataStr*(value: string): HexDataStr {.inline.} = + value.validateHexData + result = value.HexDataStr + +# Converters for use in RPC + +import json +from json_rpc/rpcserver import expect + +proc `%`*(value: HexStrings): JsonNode = + result = %(value.string) + +# Overloads to support expected representation of hex data + +proc `%`*(value: Hash256): JsonNode = + #result = %("0x" & $value) # More clean but no lowercase :( + result = %("0x" & value.data.toHex) + +proc `%`*(value: UInt256): JsonNode = + result = %("0x" & value.toString(16)) + +proc `%`*(value: PublicKey): JsonNode = + result = %("0x04" & $value) + +proc `%`*(value: PrivateKey): JsonNode = + result = %("0x" & $value) + +proc `%`*(value: SymKey): JsonNode = + result = %("0x" & value.toHex) + +proc `%`*(value: waku_protocol.Topic): JsonNode = + result = %("0x" & value.toHex) + +proc `%`*(value: seq[byte]): JsonNode = + result = %("0x" & value.toHex) + +# Helpers for the fromJson procs + +proc toPublicKey*(key: string): PublicKey {.inline.} = + result = PublicKey.fromHex(key[4 .. ^1]).tryGet() + +proc toPrivateKey*(key: string): PrivateKey {.inline.} = + result = PrivateKey.fromHex(key[2 .. ^1]).tryGet() + +proc toSymKey*(key: string): SymKey {.inline.} = + hexToByteArray(key[2 .. ^1], result) + +proc toTopic*(topic: string): waku_protocol.Topic {.inline.} = + hexToByteArray(topic[2 .. ^1], result) + +# Marshalling from JSON to Nim types that includes format checking + +func invalidMsg(name: string): string = "When marshalling from JSON, parameter \"" & name & "\" is not valid" + +proc fromJson*(n: JsonNode, argName: string, result: var HexDataStr) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidHexData: + raise newException(ValueError, invalidMsg(argName) & " as Ethereum data \"" & hexStr & "\"") + result = hexStr.hexDataStr + +proc fromJson*(n: JsonNode, argName: string, result: var Identifier) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidIdentifier: + raise newException(ValueError, invalidMsg(argName) & " as a identifier \"" & hexStr & "\"") + result = hexStr.Identifier + +proc fromJson*(n: JsonNode, argName: string, result: var UInt256) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not (hexStr.len <= 66 and hexStr.isValidHexQuantity): + raise newException(ValueError, invalidMsg(argName) & " as a UInt256 \"" & hexStr & "\"") + result = readUintBE[256](hexToPaddedByteArray[32](hexStr)) + +proc fromJson*(n: JsonNode, argName: string, result: var PublicKey) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidPublicKey: + raise newException(ValueError, invalidMsg(argName) & " as a public key \"" & hexStr & "\"") + result = hexStr.toPublicKey + +proc fromJson*(n: JsonNode, argName: string, result: var PrivateKey) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidPrivateKey: + raise newException(ValueError, invalidMsg(argName) & " as a private key \"" & hexStr & "\"") + result = hexStr.toPrivateKey + +proc fromJson*(n: JsonNode, argName: string, result: var SymKey) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidSymKey: + raise newException(ValueError, invalidMsg(argName) & " as a symmetric key \"" & hexStr & "\"") + result = toSymKey(hexStr) + +proc fromJson*(n: JsonNode, argName: string, result: var waku_protocol.Topic) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidTopic: + raise newException(ValueError, invalidMsg(argName) & " as a topic \"" & hexStr & "\"") + result = toTopic(hexStr) + +# Following procs currently required only for testing, the `createRpcSigs` macro +# requires it as it will convert the JSON results back to the original Nim +# types, but it needs the `fromJson` calls for those specific Nim types to do so +proc fromJson*(n: JsonNode, argName: string, result: var seq[byte]) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidHexData: + raise newException(ValueError, invalidMsg(argName) & " as a hex data \"" & hexStr & "\"") + result = hexToSeqByte(hexStr) + +proc fromJson*(n: JsonNode, argName: string, result: var Hash256) = + n.kind.expect(JString, argName) + let hexStr = n.getStr() + if not hexStr.isValidHash256: + raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"") + hexToByteArray(hexStr, result.data) diff --git a/waku/node/v0/rpc/key_storage.nim b/waku/node/v0/rpc/key_storage.nim new file mode 100644 index 000000000..9a341eec9 --- /dev/null +++ b/waku/node/v0/rpc/key_storage.nim @@ -0,0 +1,22 @@ +# +# Nimbus +# (c) Copyright 2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) + +import tables, eth/keys, eth/p2p/rlpx_protocols/whisper/whisper_types + +type + KeyStorage* = ref object + asymKeys*: Table[string, KeyPair] + symKeys*: Table[string, SymKey] + + KeyGenerationError* = object of CatchableError + +proc newKeyStorage*(): KeyStorage = + new(result) + result.asymKeys = initTable[string, KeyPair]() + result.symKeys = initTable[string, SymKey]() diff --git a/waku/node/v0/rpc/rpc_types.nim b/waku/node/v0/rpc/rpc_types.nim new file mode 100644 index 000000000..03b57e4af --- /dev/null +++ b/waku/node/v0/rpc/rpc_types.nim @@ -0,0 +1,58 @@ +import + hexstrings, options, eth/[keys, rlp], + eth/p2p/rlpx_protocols/waku_protocol + +#[ + Notes: + * Some of the types suppose 'null' when there is no appropriate value. + To allow for this, you can use Option[T] or use refs so the JSON transform can convert to `JNull`. + * Parameter objects from users must have their data verified so will use EthAddressStr instead of EthAddres, for example + * Objects returned to the user can use native Waku types, where hexstrings provides converters to hex strings. + This is because returned arrays in JSON is + a) not an efficient use of space + b) not the format the user expects (for example addresses are expected to be hex strings prefixed by "0x") +]# + +type + WakuInfo* = object + # Returned to user + minPow*: float64 # Current minimum PoW requirement. + # TODO: may be uint32 + maxMessageSize*: uint64 # Current message size limit in bytes. + memory*: int # Memory size of the floating messages in bytes. + messages*: int # Number of floating messages. + + WakuFilterOptions* = object + # Parameter from user + symKeyID*: Option[Identifier] # ID of symmetric key for message decryption. + privateKeyID*: Option[Identifier] # ID of private (asymmetric) key for message decryption. + sig*: Option[PublicKey] # (Optional) Public key of the signature. + minPow*: Option[float64] # (Optional) Minimal PoW requirement for incoming messages. + topics*: Option[seq[waku_protocol.Topic]] # (Optional when asym key): Array of possible topics (or partial topics). + allowP2P*: Option[bool] # (Optional) Indicates if this filter allows processing of direct peer-to-peer messages. + + WakuFilterMessage* = object + # Returned to user + sig*: Option[PublicKey] # Public key who signed this message. + recipientPublicKey*: Option[PublicKey] # The recipients public key. + ttl*: uint64 # Time-to-live in seconds. + timestamp*: uint64 # Unix timestamp of the message generation. + topic*: waku_protocol.Topic # 4 Bytes: Message topic. + payload*: seq[byte] # Decrypted payload. + padding*: seq[byte] # (Optional) Padding (byte array of arbitrary length). + pow*: float64 # Proof of work value. + hash*: Hash # Hash of the enveloped message. + + WakuPostMessage* = object + # Parameter from user + symKeyID*: Option[Identifier] # ID of symmetric key for message encryption. + pubKey*: Option[PublicKey] # Public key for message encryption. + sig*: Option[Identifier] # (Optional) ID of the signing key. + ttl*: uint64 # Time-to-live in seconds. + topic*: Option[waku_protocol.Topic] # Message topic (mandatory when key is symmetric). + payload*: HexDataStr # Payload to be encrypted. + padding*: Option[HexDataStr] # (Optional) Padding (byte array of arbitrary length). + powTime*: float64 # Maximal time in seconds to be spent on proof of work. + powTarget*: float64 # Minimal PoW target required for this message. + # TODO: EnodeStr + targetPeer*: Option[string] # (Optional) Peer ID (for peer-to-peer message only). diff --git a/waku/node/v0/rpc/waku.nim b/waku/node/v0/rpc/waku.nim new file mode 100644 index 000000000..af721b784 --- /dev/null +++ b/waku/node/v0/rpc/waku.nim @@ -0,0 +1,363 @@ +import + json_rpc/rpcserver, tables, options, sequtils, + eth/[common, rlp, keys, p2p], eth/p2p/rlpx_protocols/waku_protocol, + nimcrypto/[sysrand, hmac, sha2, pbkdf2], + rpc_types, hexstrings, key_storage + +from stew/byteutils import hexToSeqByte, hexToByteArray + +# Blatant copy of Whisper RPC but for the Waku protocol + +proc setupWakuRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) = + + rpcsrv.rpc("waku_version") do() -> string: + ## Returns string of the current Waku protocol version. + result = wakuVersionStr + + rpcsrv.rpc("waku_info") do() -> WakuInfo: + ## Returns diagnostic information about the Waku node. + let config = node.protocolState(Waku).config + result = WakuInfo(minPow: config.powRequirement, + maxMessageSize: config.maxMsgSize, + memory: 0, + messages: 0) + + # TODO: uint32 instead of uint64 is OK here, but needs to be added in json_rpc + rpcsrv.rpc("waku_setMaxMessageSize") do(size: uint64) -> bool: + ## Sets the maximal message size allowed by this node. + ## Incoming and outgoing messages with a larger size will be rejected. + ## Waku message size can never exceed the limit imposed by the underlying + ## P2P protocol (10 Mb). + ## + ## size: Message size in bytes. + ## + ## Returns true on success and an error on failure. + result = node.setMaxMessageSize(size.uint32) + if not result: + raise newException(ValueError, "Invalid size") + + rpcsrv.rpc("waku_setMinPoW") do(pow: float) -> bool: + ## Sets the minimal PoW required by this node. + ## + ## pow: The new PoW requirement. + ## + ## Returns true on success and an error on failure. + # Note: `setPowRequirement` does not raise on failures of sending the update + # to the peers. Hence in theory this should not causes errors. + await node.setPowRequirement(pow) + result = true + + # TODO: change string in to ENodeStr with extra checks + rpcsrv.rpc("waku_markTrustedPeer") do(enode: string) -> bool: + ## Marks specific peer trusted, which will allow it to send historic + ## (expired) messages. + ## Note: This function is not adding new nodes, the node needs to exists as + ## a peer. + ## + ## enode: Enode of the trusted peer. + ## + ## Returns true on success and an error on failure. + # TODO: It will now require an enode://pubkey@ip:port uri + # could also accept only the pubkey (like geth)? + let peerNode = newNode(enode) + result = node.setPeerTrusted(peerNode.id) + if not result: + raise newException(ValueError, "Not a peer") + + rpcsrv.rpc("waku_newKeyPair") do() -> Identifier: + ## Generates a new public and private key pair for message decryption and + ## encryption. + ## + ## Returns key identifier on success and an error on failure. + result = generateRandomID().Identifier + keys.asymKeys.add(result.string, KeyPair.random().tryGet()) + + rpcsrv.rpc("waku_addPrivateKey") do(key: PrivateKey) -> Identifier: + ## Stores the key pair, and returns its ID. + ## + ## key: Private key as hex bytes. + ## + ## Returns key identifier on success and an error on failure. + result = generateRandomID().Identifier + + keys.asymKeys.add(result.string, key.toKeyPair().tryGet()) + + rpcsrv.rpc("waku_deleteKeyPair") do(id: Identifier) -> bool: + ## Deletes the specifies key if it exists. + ## + ## id: Identifier of key pair + ## + ## Returns true on success and an error on failure. + var unneeded: KeyPair + result = keys.asymKeys.take(id.string, unneeded) + if not result: + raise newException(ValueError, "Invalid key id") + + rpcsrv.rpc("waku_hasKeyPair") do(id: Identifier) -> bool: + ## Checks if the Waku node has a private key of a key pair matching the + ## given ID. + ## + ## id: Identifier of key pair + ## + ## Returns (true or false) on success and an error on failure. + result = keys.asymkeys.hasKey(id.string) + + rpcsrv.rpc("waku_getPublicKey") do(id: Identifier) -> PublicKey: + ## Returns the public key for identity ID. + ## + ## id: Identifier of key pair + ## + ## Returns public key on success and an error on failure. + # Note: key not found exception as error in case not existing + result = keys.asymkeys[id.string].pubkey + + rpcsrv.rpc("waku_getPrivateKey") do(id: Identifier) -> PrivateKey: + ## Returns the private key for identity ID. + ## + ## id: Identifier of key pair + ## + ## Returns private key on success and an error on failure. + # Note: key not found exception as error in case not existing + result = keys.asymkeys[id.string].seckey + + rpcsrv.rpc("waku_newSymKey") do() -> Identifier: + ## Generates a random symmetric key and stores it under an ID, which is then + ## returned. Can be used encrypting and decrypting messages where the key is + ## known to both parties. + ## + ## Returns key identifier on success and an error on failure. + result = generateRandomID().Identifier + var key: SymKey + if randomBytes(key) != key.len: + raise newException(KeyGenerationError, "Failed generating key") + + keys.symKeys.add(result.string, key) + + + rpcsrv.rpc("waku_addSymKey") do(key: SymKey) -> Identifier: + ## Stores the key, and returns its ID. + ## + ## key: The raw key for symmetric encryption as hex bytes. + ## + ## Returns key identifier on success and an error on failure. + result = generateRandomID().Identifier + + keys.symKeys.add(result.string, key) + + rpcsrv.rpc("waku_generateSymKeyFromPassword") do(password: string) -> Identifier: + ## Generates the key from password, stores it, and returns its ID. + ## + ## password: Password. + ## + ## Returns key identifier on success and an error on failure. + ## Warning: an empty string is used as salt because the shh RPC API does not + ## allow for passing a salt. A very good password is necessary (calculate + ## yourself what that means :)) + var ctx: HMAC[sha256] + var symKey: SymKey + if pbkdf2(ctx, password, "", 65356, symKey) != sizeof(SymKey): + raise newException(KeyGenerationError, "Failed generating key") + + result = generateRandomID().Identifier + keys.symKeys.add(result.string, symKey) + + rpcsrv.rpc("waku_hasSymKey") do(id: Identifier) -> bool: + ## Returns true if there is a key associated with the name string. + ## Otherwise, returns false. + ## + ## id: Identifier of key. + ## + ## Returns (true or false) on success and an error on failure. + result = keys.symkeys.hasKey(id.string) + + rpcsrv.rpc("waku_getSymKey") do(id: Identifier) -> SymKey: + ## Returns the symmetric key associated with the given ID. + ## + ## id: Identifier of key. + ## + ## Returns Raw key on success and an error on failure. + # Note: key not found exception as error in case not existing + result = keys.symkeys[id.string] + + rpcsrv.rpc("waku_deleteSymKey") do(id: Identifier) -> bool: + ## Deletes the key associated with the name string if it exists. + ## + ## id: Identifier of key. + ## + ## Returns (true or false) on success and an error on failure. + var unneeded: SymKey + result = keys.symKeys.take(id.string, unneeded) + if not result: + raise newException(ValueError, "Invalid key id") + + rpcsrv.rpc("waku_subscribe") do(id: string, + options: WakuFilterOptions) -> Identifier: + ## Creates and registers a new subscription to receive notifications for + ## inbound Waku messages. Returns the ID of the newly created + ## subscription. + ## + ## id: identifier of function call. In case of Waku must contain the + ## value "messages". + ## options: WakuFilterOptions + ## + ## Returns the subscription ID on success, the error on failure. + + # TODO: implement subscriptions, only for WS & IPC? + discard + + rpcsrv.rpc("waku_unsubscribe") do(id: Identifier) -> bool: + ## Cancels and removes an existing subscription. + ## + ## id: Subscription identifier + ## + ## Returns true on success, the error on failure + result = node.unsubscribeFilter(id.string) + if not result: + raise newException(ValueError, "Invalid filter id") + + proc validateOptions[T,U,V](asym: Option[T], sym: Option[U], topic: Option[V]) = + if (asym.isSome() and sym.isSome()) or (asym.isNone() and sym.isNone()): + raise newException(ValueError, + "Either privateKeyID/pubKey or symKeyID must be present") + if asym.isNone() and topic.isNone(): + raise newException(ValueError, "Topic mandatory with symmetric key") + + rpcsrv.rpc("waku_newMessageFilter") do(options: WakuFilterOptions) -> Identifier: + ## Create a new filter within the node. This filter can be used to poll for + ## new messages that match the set of criteria. + ## + ## options: WakuFilterOptions + ## + ## Returns filter identifier on success, error on failure + + # Check if either symKeyID or privateKeyID is present, and not both + # Check if there are Topics when symmetric key is used + validateOptions(options.privateKeyID, options.symKeyID, options.topics) + + var + src: Option[PublicKey] + privateKey: Option[PrivateKey] + symKey: Option[SymKey] + topics: seq[waku_protocol.Topic] + powReq: float64 + allowP2P: bool + + src = options.sig + + if options.privateKeyID.isSome(): + privateKey = some(keys.asymKeys[options.privateKeyID.get().string].seckey) + + if options.symKeyID.isSome(): + symKey= some(keys.symKeys[options.symKeyID.get().string]) + + if options.minPow.isSome(): + powReq = options.minPow.get() + + if options.topics.isSome(): + topics = options.topics.get() + + if options.allowP2P.isSome(): + allowP2P = options.allowP2P.get() + + let filter = initFilter(src, privateKey, symKey, topics, powReq, allowP2P) + result = node.subscribeFilter(filter).Identifier + + # TODO: Should we do this here "automatically" or separate it in another + # RPC call? Is there a use case for that? + # Same could be said about bloomfilter, except that there is a use case + # there to have a full node no matter what message filters. + # Could also be moved to waku_protocol.nim + let config = node.protocolState(Waku).config + if config.topics.isSome(): + try: + # TODO: an addTopics call would probably be more useful + let result = await node.setTopicInterest(config.topics.get().concat(filter.topics)) + if not result: + raise newException(ValueError, "Too many topics") + except CatchableError: + trace "setTopics error occured" + elif config.isLightNode: + try: + await node.setBloomFilter(node.filtersToBloom()) + except CatchableError: + trace "setBloomFilter error occured" + + rpcsrv.rpc("waku_deleteMessageFilter") do(id: Identifier) -> bool: + ## Uninstall a message filter in the node. + ## + ## id: Filter identifier as returned when the filter was created. + ## + ## Returns true on success, error on failure. + result = node.unsubscribeFilter(id.string) + if not result: + raise newException(ValueError, "Invalid filter id") + + rpcsrv.rpc("waku_getFilterMessages") do(id: Identifier) -> seq[WakuFilterMessage]: + ## Retrieve messages that match the filter criteria and are received between + ## the last time this function was called and now. + ## + ## id: ID of filter that was created with `waku_newMessageFilter`. + ## + ## Returns array of messages on success and an error on failure. + let messages = node.getFilterMessages(id.string) + for msg in messages: + result.add WakuFilterMessage( + sig: msg.decoded.src, + recipientPublicKey: msg.dst, + ttl: msg.ttl, + topic: msg.topic, + timestamp: msg.timestamp, + payload: msg.decoded.payload, + # Note: waku_protocol padding is an Option as there is the + # possibility of 0 padding in case of custom padding. + padding: msg.decoded.padding.get(@[]), + pow: msg.pow, + hash: msg.hash) + + rpcsrv.rpc("waku_post") do(message: WakuPostMessage) -> bool: + ## Creates a Waku message and injects it into the network for + ## distribution. + ## + ## message: Waku message to post. + ## + ## Returns true on success and an error on failure. + + # Check if either symKeyID or pubKey is present, and not both + # Check if there is a Topic when symmetric key is used + validateOptions(message.pubKey, message.symKeyID, message.topic) + + var + sigPrivKey: Option[PrivateKey] + symKey: Option[SymKey] + topic: waku_protocol.Topic + padding: Option[seq[byte]] + targetPeer: Option[NodeId] + + if message.sig.isSome(): + sigPrivKey = some(keys.asymKeys[message.sig.get().string].seckey) + + if message.symKeyID.isSome(): + symKey = some(keys.symKeys[message.symKeyID.get().string]) + + # Note: If no topic it will be defaulted to 0x00000000 + if message.topic.isSome(): + topic = message.topic.get() + + if message.padding.isSome(): + padding = some(hexToSeqByte(message.padding.get().string)) + + if message.targetPeer.isSome(): + targetPeer = some(newNode(message.targetPeer.get()).id) + + result = node.postMessage(message.pubKey, + symKey, + sigPrivKey, + ttl = message.ttl.uint32, + topic = topic, + payload = hexToSeqByte(message.payload.string), + padding = padding, + powTime = message.powTime, + powTarget = message.powTarget, + targetPeer = targetPeer) + if not result: + raise newException(ValueError, "Message could not be posted") diff --git a/waku/node/v0/rpc/wakucallsigs.nim b/waku/node/v0/rpc/wakucallsigs.nim index 4476270cf..d49947ec4 100644 --- a/waku/node/v0/rpc/wakucallsigs.nim +++ b/waku/node/v0/rpc/wakucallsigs.nim @@ -1,5 +1,5 @@ proc waku_version(): string -proc waku_info(): WhisperInfo +proc waku_info(): WakuInfo proc waku_setMaxMessageSize(size: uint64): bool proc waku_setMinPoW(pow: float): bool proc waku_markTrustedPeer(enode: string): bool @@ -18,10 +18,10 @@ proc waku_hasSymKey(id: Identifier): bool proc waku_getSymKey(id: Identifier): SymKey proc waku_deleteSymKey(id: Identifier): bool -proc waku_newMessageFilter(options: WhisperFilterOptions): Identifier +proc waku_newMessageFilter(options: WakuFilterOptions): Identifier proc waku_deleteMessageFilter(id: Identifier): bool -proc waku_getFilterMessages(id: Identifier): seq[WhisperFilterMessage] -proc waku_post(message: WhisperPostMessage): bool +proc waku_getFilterMessages(id: Identifier): seq[WakuFilterMessage] +proc waku_post(message: WakuPostMessage): bool proc wakusim_generateTraffic(amount: int): bool proc wakusim_generateRandomTraffic(amount: int): bool diff --git a/waku/node/v0/rpc/wakusim.nim b/waku/node/v0/rpc/wakusim.nim new file mode 100644 index 000000000..07ee950b9 --- /dev/null +++ b/waku/node/v0/rpc/wakusim.nim @@ -0,0 +1,31 @@ +import + json_rpc/rpcserver, stew/endians2, nimcrypto/sysrand, + eth/[p2p, async_utils], eth/p2p/rlpx_protocols/waku_protocol + +proc generateTraffic(node: EthereumNode, amount = 100) {.async.} = + var topicNumber = 0'u32 + let payload = @[byte 0] + for i in 0.. bool: + traceAsyncErrors node.generateTraffic(amount) + return true + + rpcsrv.rpc("wakusim_generateRandomTraffic") do(amount: int) -> bool: + traceAsyncErrors node.generateRandomTraffic(amount) + return true diff --git a/waku/node/v0/wakunode.nim b/waku/node/v0/wakunode.nim index 48d218451..1b3571be3 100644 --- a/waku/node/v0/wakunode.nim +++ b/waku/node/v0/wakunode.nim @@ -4,7 +4,7 @@ import eth/[keys, p2p, async_utils], eth/common/utils, eth/net/nat, eth/p2p/[discovery, enode, peer_pool, bootnodes, whispernodes], eth/p2p/rlpx_protocols/[whisper_protocol, waku_protocol, waku_bridge], - ../../vendor/nimbus/nimbus/rpc/[waku, wakusim, key_storage] + ./rpc/[waku, wakusim, key_storage] const clientId = "Nimbus waku node" From a610485f752905bc97310a3ae406cb46022a2f5a Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 1 May 2020 12:05:19 +0200 Subject: [PATCH 4/9] Add protocol2 target after rebase + fix some import paths --- Makefile | 5 ++++- waku.nimble | 3 +++ waku/node/v2/quicksim.nim | 2 +- waku/node/v2/rpc/wakucallsigs.nim | 8 ++++---- waku/node/v2/rpc/wakurpc.nim | 4 +--- waku/node/v2/wakunode.nim | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 333557f04..0552ee68a 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ GIT_SUBMODULE_UPDATE := git submodule update --init --recursive else # "variables.mk" was included. Business as usual until the end of this file. # default target, because it's the first one that doesn't start with '.' -all: | wakunode +all: | wakunode wakusim # must be included after the default target -include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk @@ -77,6 +77,9 @@ wakusim2: | build deps wakunode2 echo -e $(BUILD_MSG) "build/$@" && \ $(ENV_SCRIPT) nim wakusim2 $(NIM_PARAMS) waku.nims +protocol2: + echo -e $(BUILD_MSG) "build/$@" && \ + $(ENV_SCRIPT) nim protocol2 $(NIM_PARAMS) waku.nims # symlink waku.nims: ln -s waku.nimble $@ diff --git a/waku.nimble b/waku.nimble index e5a4df73b..4bdba6cdf 100644 --- a/waku.nimble +++ b/waku.nimble @@ -47,6 +47,9 @@ task wakusim, "Build Waku simulation tools": buildBinary "quicksim", "waku/node/v0/", "-d:chronicles_log_level=INFO" buildBinary "start_network", "waku/node/v0/", "-d:chronicles_log_level=DEBUG" +task protocol2, "Build the experimental Waku protocol": + buildBinary "waku_protocol", "waku/protocol/v2/", "-d:chronicles_log_level=DEBUG" + task wakunode2, "Build Experimental Waku cli": buildBinary "wakunode", "waku/node/v2/", "-d:chronicles_log_level=TRACE" diff --git a/waku/node/v2/quicksim.nim b/waku/node/v2/quicksim.nim index 6039a1d9a..40f280c0f 100644 --- a/waku/node/v2/quicksim.nim +++ b/waku/node/v2/quicksim.nim @@ -3,7 +3,7 @@ import eth/common as eth_common, eth/keys, # XXX: Replace me eth/p2p/rlpx_protocols/waku_protocol, - ../../vendor/nimbus/nimbus/rpc/[hexstrings, rpc_types, waku], + ../v0/rpc/[hexstrings, rpc_types, waku], rpc/wakurpc, options as what # TODO: Huh? Redefinition? diff --git a/waku/node/v2/rpc/wakucallsigs.nim b/waku/node/v2/rpc/wakucallsigs.nim index b04412cf1..d3c4571d6 100644 --- a/waku/node/v2/rpc/wakucallsigs.nim +++ b/waku/node/v2/rpc/wakucallsigs.nim @@ -1,7 +1,7 @@ # NOTE: Taken from v0, only version exists right now proc waku_version(): string -proc waku_info(): WhisperInfo +proc waku_info(): WakuInfo proc waku_setMaxMessageSize(size: uint64): bool proc waku_setMinPoW(pow: float): bool proc waku_markTrustedPeer(enode: string): bool @@ -20,10 +20,10 @@ proc waku_hasSymKey(id: Identifier): bool proc waku_getSymKey(id: Identifier): SymKey proc waku_deleteSymKey(id: Identifier): bool -proc waku_newMessageFilter(options: WhisperFilterOptions): Identifier +proc waku_newMessageFilter(options: WakuFilterOptions): Identifier proc waku_deleteMessageFilter(id: Identifier): bool -proc waku_getFilterMessages(id: Identifier): seq[WhisperFilterMessage] -proc waku_post(message: WhisperPostMessage): bool +proc waku_getFilterMessages(id: Identifier): seq[WakuFilterMessage] +proc waku_post(message: WakuPostMessage): bool proc wakusim_generateTraffic(amount: int): bool proc wakusim_generateRandomTraffic(amount: int): bool diff --git a/waku/node/v2/rpc/wakurpc.nim b/waku/node/v2/rpc/wakurpc.nim index 0793b4f2e..9f79387c3 100644 --- a/waku/node/v2/rpc/wakurpc.nim +++ b/waku/node/v2/rpc/wakurpc.nim @@ -5,9 +5,7 @@ import #eth/p2p/rlpx_protocols/waku_protocol, ../../../protocol/v2/waku_protocol, nimcrypto/[sysrand, hmac, sha2, pbkdf2], - ../../../vendor/nimbus/nimbus/rpc/rpc_types, - ../../../vendor/nimbus/nimbus/rpc/hexstrings, - ../../../vendor/nimbus/nimbus/rpc/key_storage + ../../v0/rpc/[rpc_types, hexstrings, key_storage] from stew/byteutils import hexToSeqByte, hexToByteArray diff --git a/waku/node/v2/wakunode.nim b/waku/node/v2/wakunode.nim index 6e9cebd5c..cedcd679d 100644 --- a/waku/node/v2/wakunode.nim +++ b/waku/node/v2/wakunode.nim @@ -5,7 +5,7 @@ import eth/p2p/[discovery, enode, peer_pool, bootnodes, whispernodes], eth/p2p/rlpx_protocols/[whisper_protocol, waku_protocol, waku_bridge], # TODO remove me - ../../vendor/nimbus/nimbus/rpc/[wakusim, key_storage], + ../v0/rpc/[wakusim, key_storage], ../../vendor/nim-libp2p/libp2p/standard_setup, ../../vendor/nim-libp2p/libp2p/multiaddress, ../../vendor/nim-libp2p/libp2p/crypto/crypto, From bcff4b912ec72df4d5ae383c79c7112aea492694 Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 1 May 2020 13:55:07 +0200 Subject: [PATCH 5/9] Add appveyor and travis yaml files --- .appveyor.yml | 36 ++++++++++++++++++++++++++++++++++++ .travis.yml | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 .appveyor.yml create mode 100644 .travis.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..34c8da90c --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,36 @@ +version: '{build}' + +image: Visual Studio 2015 + +init: # Scripts called at the very beginning + # Enable paths > 260 characters + - ps: Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 + - git config --global core.longpaths true + +cache: + - NimBinaries + +matrix: + # We always want 32 and 64-bit compilation + fast_finish: false + +platform: + - x64 + - x86 + +install: + # use the newest versions documented here: https://www.appveyor.com/docs/windows-images-software/#mingw-msys-cygwin + - IF "%PLATFORM%" == "x86" SET PATH=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin;%PATH% + - IF "%PLATFORM%" == "x64" SET PATH=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH% + +build_script: + # the 32-bit build is done on a 64-bit image, so we need to override the architecture + - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% CI_CACHE=NimBinaries update + - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% fetch-dlls + +test_script: + - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% LOG_LEVEL=TRACE + - build\wakunode.exe --help + - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% test + +deploy: off diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e86a58c61 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,48 @@ +language: c + +dist: bionic + +# https://docs.travis-ci.com/user/caching/ +cache: + ccache: true + directories: + - vendor/nimbus-build-system/vendor/Nim/bin + +git: + # when multiple CI builds are queued, the tested commit needs to be in the last X commits cloned with "--depth X" + depth: 10 + +matrix: + include: + - os: linux + arch: amd64 + sudo: required + env: + - NPROC=2 + before_install: + - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + - sudo apt-get -q update + - os: linux + arch: arm64 + sudo: required + env: + - NPROC=6 # Worth trying more than 2 parallel jobs: https://travis-ci.community/t/no-cache-support-on-arm64/5416/8 + # (also used to get a different cache key than the amd64 one) + before_install: + - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + - sudo apt-get -q update + - sudo apt-get install -y libpcre3-dev + - os: osx + before_install: + - HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install ccache + env: + - NPROC=2 + +script: + - set -e # fail fast + # Building Nim-1.0.4 takes up to 10 minutes on Travis - the time limit after which jobs are cancelled for having no output + - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" V=1 update # to allow a newer Nim version to be detected + - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" LOG_LEVEL=TRACE + - build/wakunode --help + - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" test + From 50e1a2680d01398110d1bf41a986903a916d8105 Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 1 May 2020 14:43:25 +0200 Subject: [PATCH 6/9] Move waku_protocol + tests from nim-eth --- tests/all_tests.nim | 3 + tests/test_helpers.nim | 32 + tests/test_rpc_waku.nim | 11 +- tests/test_waku_bridge.nim | 95 +++ tests/test_waku_connect.nim | 242 +++++++ tests/test_waku_mail.nim | 116 ++++ waku.nimble | 6 +- waku/node/README.md | 2 +- waku/node/{v0 => v1}/README.md | 0 waku/node/{v0 => v1}/config.nim | 0 waku/node/{v0 => v1}/docker/Dockerfile | 0 waku/node/{v0 => v1}/docker/Makefile | 0 .../examples/waku-grafana-dashboard.json | 0 .../metrics/prometheus/prometheus.yml | 0 .../waku-sim-all-nodes-grafana-dashboard.json | 0 waku/node/{v0 => v1}/nim.cfg | 0 waku/node/{v0 => v1}/quicksim.nim | 4 +- waku/node/{v0 => v1}/rpc/hexstrings.nim | 2 +- waku/node/{v0 => v1}/rpc/key_storage.nim | 0 waku/node/{v0 => v1}/rpc/rpc_types.nim | 2 +- waku/node/{v0 => v1}/rpc/waku.nim | 5 +- waku/node/{v0 => v1}/rpc/wakucallsigs.nim | 0 waku/node/{v0 => v1}/rpc/wakusim.nim | 3 +- waku/node/{v0 => v1}/start_network.nim | 0 waku/node/{v0 => v1}/wakunode.nim | 3 +- waku/node/v2/config.nim | 2 +- waku/node/v2/quicksim.nim | 6 +- waku/node/v2/rpc/wakucallsigs.nim | 2 +- waku/node/v2/rpc/wakurpc.nim | 4 +- waku/node/v2/wakunode.nim | 2 +- waku/protocol/v1/waku_bridge.nim | 17 + waku/protocol/v1/waku_mail.nim | 86 +++ waku/protocol/v1/waku_protocol.nim | 649 ++++++++++++++++++ 33 files changed, 1268 insertions(+), 26 deletions(-) create mode 100644 tests/test_helpers.nim create mode 100644 tests/test_waku_bridge.nim create mode 100644 tests/test_waku_connect.nim create mode 100644 tests/test_waku_mail.nim rename waku/node/{v0 => v1}/README.md (100%) rename waku/node/{v0 => v1}/config.nim (100%) rename waku/node/{v0 => v1}/docker/Dockerfile (100%) rename waku/node/{v0 => v1}/docker/Makefile (100%) rename waku/node/{v0 => v1}/examples/waku-grafana-dashboard.json (100%) rename waku/node/{v0 => v1}/metrics/prometheus/prometheus.yml (100%) rename waku/node/{v0 => v1}/metrics/waku-sim-all-nodes-grafana-dashboard.json (100%) rename waku/node/{v0 => v1}/nim.cfg (100%) rename waku/node/{v0 => v1}/quicksim.nim (96%) rename waku/node/{v0 => v1}/rpc/hexstrings.nim (99%) rename waku/node/{v0 => v1}/rpc/key_storage.nim (100%) rename waku/node/{v0 => v1}/rpc/rpc_types.nim (98%) rename waku/node/{v0 => v1}/rpc/waku.nim (99%) rename waku/node/{v0 => v1}/rpc/wakucallsigs.nim (100%) rename waku/node/{v0 => v1}/rpc/wakusim.nim (94%) rename waku/node/{v0 => v1}/start_network.nim (100%) rename waku/node/{v0 => v1}/wakunode.nim (98%) create mode 100644 waku/protocol/v1/waku_bridge.nim create mode 100644 waku/protocol/v1/waku_mail.nim create mode 100644 waku/protocol/v1/waku_protocol.nim diff --git a/tests/all_tests.nim b/tests/all_tests.nim index 1948456c2..046f7bedc 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -1,2 +1,5 @@ import + ./test_waku_connect, + ./test_waku_bridge, + ./test_waku_mail, ./test_rpc_waku \ No newline at end of file diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim new file mode 100644 index 000000000..b7c5bf351 --- /dev/null +++ b/tests/test_helpers.nim @@ -0,0 +1,32 @@ +import + unittest, chronos, strutils, + eth/[keys, p2p] + +var nextPort = 30303 + +proc localAddress*(port: int): Address = + let port = Port(port) + result = Address(udpPort: port, tcpPort: port, + ip: parseIpAddress("127.0.0.1")) + +proc setupTestNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = + let keys1 = KeyPair.random()[] + result = newEthereumNode(keys1, localAddress(nextPort), 1, nil, + addAllCapabilities = false) + nextPort.inc + for capability in capabilities: + result.addCapability capability + +template asyncTest*(name, body: untyped) = + test name: + proc scenario {.async.} = body + waitFor scenario() + +template procSuite*(name, body: untyped) = + proc suitePayload = + suite name: + body + + suitePayload() + +template sourceDir*: string = currentSourcePath.rsplit(DirSep, 1)[0] diff --git a/tests/test_rpc_waku.nim b/tests/test_rpc_waku.nim index eb8e26049..f2829d79b 100644 --- a/tests/test_rpc_waku.nim +++ b/tests/test_rpc_waku.nim @@ -1,16 +1,15 @@ import unittest, strformat, options, stew/byteutils, json_rpc/[rpcserver, rpcclient], eth/common as eth_common, eth/[rlp, keys, p2p], - eth/p2p/rlpx_protocols/waku_protocol, - ../waku/node/v0/rpc/[hexstrings, rpc_types, waku, key_storage] + ../waku/protocol/v1/waku_protocol, + ../waku/node/v1/rpc/[hexstrings, rpc_types, waku, key_storage], + ./test_helpers from os import DirSep, ParDir -from strutils import rsplit -template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0] ## Generate client convenience marshalling wrappers from forward declarations -## For testing, ethcallsigs needs to be kept in sync with ../waku/node/v0/rpc/waku -const sigPath = &"{sourceDir}{DirSep}{ParDir}{DirSep}waku{DirSep}node{DirSep}v0{DirSep}rpc{DirSep}wakucallsigs.nim" +## For testing, ethcallsigs needs to be kept in sync with ../waku/node/v1/rpc/waku +const sigPath = &"{sourceDir}{DirSep}{ParDir}{DirSep}waku{DirSep}node{DirSep}v1{DirSep}rpc{DirSep}wakucallsigs.nim" createRpcSigs(RpcSocketClient, sigPath) proc setupNode(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = diff --git a/tests/test_waku_bridge.nim b/tests/test_waku_bridge.nim new file mode 100644 index 000000000..53ad2607a --- /dev/null +++ b/tests/test_waku_bridge.nim @@ -0,0 +1,95 @@ +# +# Waku +# (c) Copyright 2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) + +import + sequtils, unittest, tables, chronos, eth/p2p, eth/p2p/peer_pool, + eth/p2p/rlpx_protocols/whisper_protocol as whisper, + ../waku/protocol/v1/waku_protocol as waku, + ../waku/protocol/v1/waku_bridge, + ./test_helpers + +let safeTTL = 5'u32 +let waitInterval = waku.messageInterval + 150.milliseconds + +procSuite "Waku - Whisper bridge tests": + # Waku Whisper node has both capabilities, listens to Whisper and Waku and + # relays traffic between the two. + var + nodeWakuWhisper = setupTestNode(Whisper, Waku) # This will be the bridge + nodeWhisper = setupTestNode(Whisper) + nodeWaku = setupTestNode(Waku) + + nodeWakuWhisper.startListening() + let bridgeNode = newNode(nodeWakuWhisper.toENode()) + nodeWakuWhisper.shareMessageQueue() + + waitFor nodeWhisper.peerPool.connectToNode(bridgeNode) + waitFor nodeWaku.peerPool.connectToNode(bridgeNode) + + asyncTest "WakuWhisper and Whisper peers connected": + check: + nodeWhisper.peerPool.connectedNodes.len() == 1 + nodeWaku.peerPool.connectedNodes.len() == 1 + + asyncTest "Whisper - Waku communcation via bridge": + # topic whisper node subscribes to, waku node posts to + let topic1 = [byte 0x12, 0, 0, 0] + # topic waku node subscribes to, whisper node posts to + let topic2 = [byte 0x34, 0, 0, 0] + var payloads = [repeat(byte 0, 10), repeat(byte 1, 10)] + var futures = [newFuture[int](), newFuture[int]()] + + proc handler1(msg: whisper.ReceivedMessage) = + check msg.decoded.payload == payloads[0] + futures[0].complete(1) + proc handler2(msg: waku.ReceivedMessage) = + check msg.decoded.payload == payloads[1] + futures[1].complete(1) + + var filter1 = whisper.subscribeFilter(nodeWhisper, + whisper.initFilter(topics = @[topic1]), handler1) + var filter2 = waku.subscribeFilter(nodeWaku, + waku.initFilter(topics = @[topic2]), handler2) + + check: + # Message should also end up in the Whisper node its queue via the bridge + waku.postMessage(nodeWaku, ttl = safeTTL + 1, topic = topic1, + payload = payloads[0]) == true + # Message should also end up in the Waku node its queue via the bridge + whisper.postMessage(nodeWhisper, ttl = safeTTL, topic = topic2, + payload = payloads[1]) == true + nodeWhisper.protocolState(Whisper).queue.items.len == 1 + nodeWaku.protocolState(Waku).queue.items.len == 1 + + # waitInterval*2 as messages have to pass the bridge also (2 hops) + await allFutures(futures).withTimeout(waitInterval*2) + + # Relay can receive Whisper & Waku messages + nodeWakuWhisper.protocolState(Whisper).queue.items.len == 2 + nodeWakuWhisper.protocolState(Waku).queue.items.len == 2 + + # Whisper node can receive Waku messages (via bridge) + nodeWhisper.protocolState(Whisper).queue.items.len == 2 + # Waku node can receive Whisper messages (via bridge) + nodeWaku.protocolState(Waku).queue.items.len == 2 + + whisper.unsubscribeFilter(nodeWhisper, filter1) == true + waku.unsubscribeFilter(nodeWaku, filter2) == true + + # XXX: This reads a bit weird, but eh + waku.resetMessageQueue(nodeWaku) + whisper.resetMessageQueue(nodeWhisper) + # shared queue so Waku and Whisper should be set to 0 + waku.resetMessageQueue(nodeWakuWhisper) + + check: + nodeWhisper.protocolState(Whisper).queue.items.len == 0 + nodeWaku.protocolState(Waku).queue.items.len == 0 + nodeWakuWhisper.protocolState(Whisper).queue.items.len == 0 + nodeWakuWhisper.protocolState(Waku).queue.items.len == 0 diff --git a/tests/test_waku_connect.nim b/tests/test_waku_connect.nim new file mode 100644 index 000000000..6d0f18cde --- /dev/null +++ b/tests/test_waku_connect.nim @@ -0,0 +1,242 @@ +# +# Waku +# (c) Copyright 2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) + +import + sequtils, tables, unittest, chronos, eth/[keys, p2p], eth/p2p/peer_pool, + ../waku/protocol/v1/waku_protocol, + ./test_helpers + +const + safeTTL = 5'u32 + waitInterval = messageInterval + 150.milliseconds + conditionTimeoutMs = 3000 + +# check on a condition until true or return a future containing false +# if timeout expires first +proc eventually(timeout: int, condition: proc(): bool {.gcsafe.}): Future[bool] = + let wrappedCondition = proc(): Future[bool] {.async.} = + let f = newFuture[bool]() + while not condition(): + await sleepAsync(100.milliseconds) + f.complete(true) + return await f + return withTimeout(wrappedCondition(), timeout) + +# TODO: Just repeat all the test_shh_connect tests here that are applicable or +# have some commonly shared test code for both protocols. +suite "Waku connections": + asyncTest "Waku connections": + var + n1 = setupTestNode(Waku) + n2 = setupTestNode(Waku) + n3 = setupTestNode(Waku) + n4 = setupTestNode(Waku) + + var topics: seq[Topic] + n1.protocolState(Waku).config.topics = some(topics) + n2.protocolState(Waku).config.topics = some(topics) + n3.protocolState(Waku).config.topics = none(seq[Topic]) + n4.protocolState(Waku).config.topics = none(seq[Topic]) + + n1.startListening() + n3.startListening() + + let + p1 = await n2.rlpxConnect(newNode(n1.toENode())) + p2 = await n2.rlpxConnect(newNode(n3.toENode())) + p3 = await n4.rlpxConnect(newNode(n3.toENode())) + check: + p1.isNil + p2.isNil == false + p3.isNil == false + + asyncTest "Waku set-topic-interest": + var + wakuTopicNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + let + topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] + topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] + wrongTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] + + # Set one topic so we are not considered a full node + wakuTopicNode.protocolState(Waku).config.topics = some(@[topic1]) + + wakuNode.startListening() + await wakuTopicNode.peerPool.connectToNode(newNode(wakuNode.toENode())) + + # Update topic interest + check: + await setTopicInterest(wakuTopicNode, @[topic1, topic2]) + + let payload = repeat(byte 0, 10) + check: + wakuNode.postMessage(ttl = safeTTL, topic = topic1, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = topic2, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = wrongTopic, payload = payload) + wakuNode.protocolState(Waku).queue.items.len == 3 + await sleepAsync(waitInterval) + check: + wakuTopicNode.protocolState(Waku).queue.items.len == 2 + + asyncTest "Waku set-minimum-pow": + var + wakuPowNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + wakuNode.startListening() + await wakuPowNode.peerPool.connectToNode(newNode(wakuNode.toENode())) + + # Update minimum pow + await setPowRequirement(wakuPowNode, 1.0) + await sleepAsync(waitInterval) + + check: + wakuNode.peerPool.len == 1 + + # check powRequirement is updated + for peer in wakuNode.peerPool.peers: + check: + peer.state(Waku).powRequirement == 1.0 + + asyncTest "Waku set-light-node": + var + wakuLightNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + wakuNode.startListening() + await wakuLightNode.peerPool.connectToNode(newNode(wakuNode.toENode())) + + # Update minimum pow + await setLightNode(wakuLightNode, true) + await sleepAsync(waitInterval) + + check: + wakuNode.peerPool.len == 1 + + # check lightNode is updated + for peer in wakuNode.peerPool.peers: + check: + peer.state(Waku).isLightNode + + asyncTest "Waku set-bloom-filter": + var + wakuBloomNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + bloom = fullBloom() + topics = @[[byte 0xDA, 0xDA, 0xDA, 0xAA]] + + # Set topic interest + discard await wakuBloomNode.setTopicInterest(topics) + + wakuBloomNode.startListening() + await wakuNode.peerPool.connectToNode(newNode(wakuBloomNode.toENode())) + + # Sanity check + check: + wakuNode.peerPool.len == 1 + + # check bloom filter is updated + for peer in wakuNode.peerPool.peers: + check: + peer.state(Waku).bloom == bloom + peer.state(Waku).topics == some(topics) + + let hasBloomNodeConnectedCondition = proc(): bool = wakuBloomNode.peerPool.len == 1 + # wait for the peer to be connected on the other side + let hasBloomNodeConnected = await eventually(conditionTimeoutMs, hasBloomNodeConnectedCondition) + # check bloom filter is updated + check: + hasBloomNodeConnected + + # disable one bit in the bloom filter + bloom[0] = 0x0 + + # and set it + await setBloomFilter(wakuBloomNode, bloom) + + let bloomFilterUpdatedCondition = proc(): bool = + for peer in wakuNode.peerPool.peers: + return peer.state(Waku).bloom == bloom and peer.state(Waku).topics == none(seq[Topic]) + + let bloomFilterUpdated = await eventually(conditionTimeoutMs, bloomFilterUpdatedCondition) + # check bloom filter is updated + check: + bloomFilterUpdated + + asyncTest "Waku topic-interest": + var + wakuTopicNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + let + topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] + topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] + wrongTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] + + wakuTopicNode.protocolState(Waku).config.topics = some(@[topic1, topic2]) + + wakuNode.startListening() + await wakuTopicNode.peerPool.connectToNode(newNode(wakuNode.toENode())) + + let payload = repeat(byte 0, 10) + check: + wakuNode.postMessage(ttl = safeTTL, topic = topic1, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = topic2, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = wrongTopic, payload = payload) + wakuNode.protocolState(Waku).queue.items.len == 3 + + let response = await eventually(conditionTimeoutMs, proc (): bool = wakuTopicNode.protocolState(Waku).queue.items.len == 2) + check: + response + + asyncTest "Waku topic-interest versus bloom filter": + var + wakuTopicNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + let + topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] + topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] + bloomTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] + + # It was checked that the topics don't trigger false positives on the bloom. + wakuTopicNode.protocolState(Waku).config.topics = some(@[topic1, topic2]) + wakuTopicNode.protocolState(Waku).config.bloom = some(toBloom([bloomTopic])) + + wakuNode.startListening() + await wakuTopicNode.peerPool.connectToNode(newNode(wakuNode.toENode())) + + let payload = repeat(byte 0, 10) + check: + wakuNode.postMessage(ttl = safeTTL, topic = topic1, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = topic2, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = bloomTopic, payload = payload) + wakuNode.protocolState(Waku).queue.items.len == 3 + await sleepAsync(waitInterval) + check: + wakuTopicNode.protocolState(Waku).queue.items.len == 2 + + asyncTest "Light node posting": + var ln = setupTestNode(Waku) + await ln.setLightNode(true) + var fn = setupTestNode(Waku) + fn.startListening() + await ln.peerPool.connectToNode(newNode(fn.toENode())) + + let topic = [byte 0, 0, 0, 0] + + check: + ln.peerPool.connectedNodes.len() == 1 + # normal post + ln.postMessage(ttl = safeTTL, topic = topic, + payload = repeat(byte 0, 10)) == true + ln.protocolState(Waku).queue.items.len == 1 + # TODO: add test on message relaying diff --git a/tests/test_waku_mail.nim b/tests/test_waku_mail.nim new file mode 100644 index 000000000..a19df5cd6 --- /dev/null +++ b/tests/test_waku_mail.nim @@ -0,0 +1,116 @@ +import + unittest, chronos, tables, sequtils, times, + eth/[p2p, async_utils], eth/p2p/peer_pool, + ../waku/protocol/v1/[waku_protocol, waku_mail], + ./test_helpers + +const + transmissionTimeout = chronos.milliseconds(100) + +proc waitForConnected(node: EthereumNode) {.async.} = + while node.peerPool.connectedNodes.len == 0: + await sleepAsync(chronos.milliseconds(1)) + +procSuite "Waku Mail Client": + var client = setupTestNode(Waku) + var simpleServer = setupTestNode(Waku) + + simpleServer.startListening() + let simpleServerNode = newNode(simpleServer.toENode()) + let clientNode = newNode(client.toENode()) + waitFor client.peerPool.connectToNode(simpleServerNode) + require: + waitFor simpleServer.waitForConnected().withTimeout(transmissionTimeout) + + asyncTest "Two peers connected": + check: + client.peerPool.connectedNodes.len() == 1 + simpleServer.peerPool.connectedNodes.len() == 1 + + asyncTest "Mail Request and Request Complete": + let + topic = [byte 0, 0, 0, 0] + bloom = toBloom(@[topic]) + lower = 0'u32 + upper = epochTime().uint32 + limit = 100'u32 + request = MailRequest(lower: lower, upper: upper, bloom: @bloom, + limit: limit) + + var symKey: SymKey + check client.setPeerTrusted(simpleServerNode.id) + var cursorFut = client.requestMail(simpleServerNode.id, request, symKey, 1) + + # Simple mailserver part + let peer = simpleServer.peerPool.connectedNodes[clientNode] + var f = peer.nextMsg(Waku.p2pRequest) + require await f.withTimeout(transmissionTimeout) + let response = f.read() + let decoded = decode(response.envelope.data, symKey = some(symKey)) + require decoded.isSome() + + var rlp = rlpFromBytes(decoded.get().payload) + let output = rlp.read(MailRequest) + check: + output.lower == lower + output.upper == upper + output.bloom == bloom + output.limit == limit + + var dummy: Hash + await peer.p2pRequestComplete(dummy, dummy, @[]) + + check await cursorFut.withTimeout(transmissionTimeout) + + asyncTest "Mail Send": + let topic = [byte 0x12, 0x34, 0x56, 0x78] + let payload = repeat(byte 0, 10) + var f = newFuture[int]() + + proc handler(msg: ReceivedMessage) = + check msg.decoded.payload == payload + f.complete(1) + + let filter = subscribeFilter(client, + initFilter(topics = @[topic], allowP2P = true), handler) + + check: + client.setPeerTrusted(simpleServerNode.id) + # ttl 0 to show that ttl should be ignored + # TODO: perhaps not the best way to test this, means no PoW calculation + # may be done, and not sure if that is OK? + simpleServer.postMessage(ttl = 0, topic = topic, payload = payload, + targetPeer = some(clientNode.id)) + + await f.withTimeout(transmissionTimeout) + + client.unsubscribeFilter(filter) + + asyncTest "Multiple Client Request and Complete": + var count = 5 + proc customHandler(peer: Peer, envelope: Envelope)= + var envelopes: seq[Envelope] + traceAsyncErrors peer.p2pMessage(envelopes) + + var cursor: seq[byte] + count = count - 1 + if count == 0: + cursor = @[] + else: + cursor = @[byte count] + + var dummy: Hash + traceAsyncErrors peer.p2pRequestComplete(dummy, dummy, cursor) + + simpleServer.enableMailServer(customHandler) + check client.setPeerTrusted(simpleServerNode.id) + var request: MailRequest + var symKey: SymKey + let cursor = + await client.requestMail(simpleServerNode.id, request, symKey, 5) + require cursor.isSome() + check: + cursor.get().len == 0 + count == 0 + + # TODO: Also check for received envelopes. diff --git a/waku.nimble b/waku.nimble index 4bdba6cdf..b99d8dbcc 100644 --- a/waku.nimble +++ b/waku.nimble @@ -41,11 +41,11 @@ task test, "Run tests": test "all_tests" task wakunode, "Build Waku cli": - buildBinary "wakunode", "waku/node/v0/", "-d:chronicles_log_level=TRACE" + buildBinary "wakunode", "waku/node/v1/", "-d:chronicles_log_level=TRACE" task wakusim, "Build Waku simulation tools": - buildBinary "quicksim", "waku/node/v0/", "-d:chronicles_log_level=INFO" - buildBinary "start_network", "waku/node/v0/", "-d:chronicles_log_level=DEBUG" + buildBinary "quicksim", "waku/node/v1/", "-d:chronicles_log_level=INFO" + buildBinary "start_network", "waku/node/v1/", "-d:chronicles_log_level=DEBUG" task protocol2, "Build the experimental Waku protocol": buildBinary "waku_protocol", "waku/protocol/v2/", "-d:chronicles_log_level=DEBUG" diff --git a/waku/node/README.md b/waku/node/README.md index ff169893a..318b90e91 100644 --- a/waku/node/README.md +++ b/waku/node/README.md @@ -2,4 +2,4 @@ TODO. -See README in `v0` folder for instructions on how to run a node. +See README in `v1` folder for instructions on how to run a node. diff --git a/waku/node/v0/README.md b/waku/node/v1/README.md similarity index 100% rename from waku/node/v0/README.md rename to waku/node/v1/README.md diff --git a/waku/node/v0/config.nim b/waku/node/v1/config.nim similarity index 100% rename from waku/node/v0/config.nim rename to waku/node/v1/config.nim diff --git a/waku/node/v0/docker/Dockerfile b/waku/node/v1/docker/Dockerfile similarity index 100% rename from waku/node/v0/docker/Dockerfile rename to waku/node/v1/docker/Dockerfile diff --git a/waku/node/v0/docker/Makefile b/waku/node/v1/docker/Makefile similarity index 100% rename from waku/node/v0/docker/Makefile rename to waku/node/v1/docker/Makefile diff --git a/waku/node/v0/examples/waku-grafana-dashboard.json b/waku/node/v1/examples/waku-grafana-dashboard.json similarity index 100% rename from waku/node/v0/examples/waku-grafana-dashboard.json rename to waku/node/v1/examples/waku-grafana-dashboard.json diff --git a/waku/node/v0/metrics/prometheus/prometheus.yml b/waku/node/v1/metrics/prometheus/prometheus.yml similarity index 100% rename from waku/node/v0/metrics/prometheus/prometheus.yml rename to waku/node/v1/metrics/prometheus/prometheus.yml diff --git a/waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json b/waku/node/v1/metrics/waku-sim-all-nodes-grafana-dashboard.json similarity index 100% rename from waku/node/v0/metrics/waku-sim-all-nodes-grafana-dashboard.json rename to waku/node/v1/metrics/waku-sim-all-nodes-grafana-dashboard.json diff --git a/waku/node/v0/nim.cfg b/waku/node/v1/nim.cfg similarity index 100% rename from waku/node/v0/nim.cfg rename to waku/node/v1/nim.cfg diff --git a/waku/node/v0/quicksim.nim b/waku/node/v1/quicksim.nim similarity index 96% rename from waku/node/v0/quicksim.nim rename to waku/node/v1/quicksim.nim index 200bc5200..49eae4c65 100644 --- a/waku/node/v0/quicksim.nim +++ b/waku/node/v1/quicksim.nim @@ -1,7 +1,7 @@ import os, strformat, chronicles, json_rpc/[rpcclient, rpcserver], nimcrypto/sysrand, - eth/common as eth_common, eth/keys, eth/p2p/rlpx_protocols/waku_protocol, - ./rpc/[hexstrings, rpc_types], + eth/common as eth_common, eth/keys, + ../../protocol/v1/waku_protocol, ./rpc/[hexstrings, rpc_types], options as what # TODO: Huh? Redefinition? from os import DirSep diff --git a/waku/node/v0/rpc/hexstrings.nim b/waku/node/v1/rpc/hexstrings.nim similarity index 99% rename from waku/node/v0/rpc/hexstrings.nim rename to waku/node/v1/rpc/hexstrings.nim index d5051996e..c015ec5a3 100644 --- a/waku/node/v0/rpc/hexstrings.nim +++ b/waku/node/v1/rpc/hexstrings.nim @@ -26,7 +26,7 @@ import stint, stew/byteutils, eth/[keys, rlp], eth/common/eth_types, - eth/p2p/rlpx_protocols/waku_protocol + ../../../protocol/v1/waku_protocol type HexDataStr* = distinct string diff --git a/waku/node/v0/rpc/key_storage.nim b/waku/node/v1/rpc/key_storage.nim similarity index 100% rename from waku/node/v0/rpc/key_storage.nim rename to waku/node/v1/rpc/key_storage.nim diff --git a/waku/node/v0/rpc/rpc_types.nim b/waku/node/v1/rpc/rpc_types.nim similarity index 98% rename from waku/node/v0/rpc/rpc_types.nim rename to waku/node/v1/rpc/rpc_types.nim index 03b57e4af..582a9cb1b 100644 --- a/waku/node/v0/rpc/rpc_types.nim +++ b/waku/node/v1/rpc/rpc_types.nim @@ -1,6 +1,6 @@ import hexstrings, options, eth/[keys, rlp], - eth/p2p/rlpx_protocols/waku_protocol + ../../../protocol/v1/waku_protocol #[ Notes: diff --git a/waku/node/v0/rpc/waku.nim b/waku/node/v1/rpc/waku.nim similarity index 99% rename from waku/node/v0/rpc/waku.nim rename to waku/node/v1/rpc/waku.nim index af721b784..b8439f5e1 100644 --- a/waku/node/v0/rpc/waku.nim +++ b/waku/node/v1/rpc/waku.nim @@ -1,8 +1,9 @@ import json_rpc/rpcserver, tables, options, sequtils, - eth/[common, rlp, keys, p2p], eth/p2p/rlpx_protocols/waku_protocol, + eth/[common, rlp, keys, p2p], nimcrypto/[sysrand, hmac, sha2, pbkdf2], - rpc_types, hexstrings, key_storage + rpc_types, hexstrings, key_storage, + ../../../protocol/v1/waku_protocol from stew/byteutils import hexToSeqByte, hexToByteArray diff --git a/waku/node/v0/rpc/wakucallsigs.nim b/waku/node/v1/rpc/wakucallsigs.nim similarity index 100% rename from waku/node/v0/rpc/wakucallsigs.nim rename to waku/node/v1/rpc/wakucallsigs.nim diff --git a/waku/node/v0/rpc/wakusim.nim b/waku/node/v1/rpc/wakusim.nim similarity index 94% rename from waku/node/v0/rpc/wakusim.nim rename to waku/node/v1/rpc/wakusim.nim index 07ee950b9..08446ad2b 100644 --- a/waku/node/v0/rpc/wakusim.nim +++ b/waku/node/v1/rpc/wakusim.nim @@ -1,6 +1,7 @@ import json_rpc/rpcserver, stew/endians2, nimcrypto/sysrand, - eth/[p2p, async_utils], eth/p2p/rlpx_protocols/waku_protocol + eth/[p2p, async_utils], + ../../../protocol/v1/waku_protocol proc generateTraffic(node: EthereumNode, amount = 100) {.async.} = var topicNumber = 0'u32 diff --git a/waku/node/v0/start_network.nim b/waku/node/v1/start_network.nim similarity index 100% rename from waku/node/v0/start_network.nim rename to waku/node/v1/start_network.nim diff --git a/waku/node/v0/wakunode.nim b/waku/node/v1/wakunode.nim similarity index 98% rename from waku/node/v0/wakunode.nim rename to waku/node/v1/wakunode.nim index 1b3571be3..346318dac 100644 --- a/waku/node/v0/wakunode.nim +++ b/waku/node/v1/wakunode.nim @@ -3,7 +3,8 @@ import chronicles/topics_registry, # TODO: What? Need this for setLoglevel, weird. eth/[keys, p2p, async_utils], eth/common/utils, eth/net/nat, eth/p2p/[discovery, enode, peer_pool, bootnodes, whispernodes], - eth/p2p/rlpx_protocols/[whisper_protocol, waku_protocol, waku_bridge], + eth/p2p/rlpx_protocols/whisper_protocol, + ../../protocol/v1/[waku_protocol, waku_bridge], ./rpc/[waku, wakusim, key_storage] const clientId = "Nimbus waku node" diff --git a/waku/node/v2/config.nim b/waku/node/v2/config.nim index f12951468..71cd78c9c 100644 --- a/waku/node/v2/config.nim +++ b/waku/node/v2/config.nim @@ -1,6 +1,6 @@ import confutils/defs, chronicles, chronos, - eth/keys, eth/p2p/rlpx_protocols/waku_protocol + eth/keys type Fleet* = enum diff --git a/waku/node/v2/quicksim.nim b/waku/node/v2/quicksim.nim index 40f280c0f..54c5f8e07 100644 --- a/waku/node/v2/quicksim.nim +++ b/waku/node/v2/quicksim.nim @@ -2,8 +2,8 @@ import os, strformat, chronicles, json_rpc/[rpcclient, rpcserver], nimcrypto/sysrand, eth/common as eth_common, eth/keys, # XXX: Replace me - eth/p2p/rlpx_protocols/waku_protocol, - ../v0/rpc/[hexstrings, rpc_types, waku], + ../../protocol/v1/waku_protocol, + ../v1/rpc/[hexstrings, rpc_types, waku], rpc/wakurpc, options as what # TODO: Huh? Redefinition? @@ -14,7 +14,7 @@ template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0] const sigWakuPath = &"{sourceDir}{DirSep}rpc{DirSep}wakucallsigs.nim" createRpcSigs(RpcHttpClient, sigWakuPath) -# More minimal than v0 quicksim, just RPC client for now +# More minimal than v1 quicksim, just RPC client for now let node1 = newRpcHttpClient() #let node2 = newRpcHttpClient() diff --git a/waku/node/v2/rpc/wakucallsigs.nim b/waku/node/v2/rpc/wakucallsigs.nim index d3c4571d6..ba6ba5185 100644 --- a/waku/node/v2/rpc/wakucallsigs.nim +++ b/waku/node/v2/rpc/wakucallsigs.nim @@ -1,4 +1,4 @@ -# NOTE: Taken from v0, only version exists right now +# NOTE: Taken from v1, only version exists right now proc waku_version(): string proc waku_info(): WakuInfo diff --git a/waku/node/v2/rpc/wakurpc.nim b/waku/node/v2/rpc/wakurpc.nim index 9f79387c3..c6f6ae33f 100644 --- a/waku/node/v2/rpc/wakurpc.nim +++ b/waku/node/v2/rpc/wakurpc.nim @@ -2,10 +2,10 @@ import json_rpc/rpcserver, tables, options, eth/[common, rlp, keys, p2p], #DevP2P impl - #eth/p2p/rlpx_protocols/waku_protocol, + # ../../../protocol/v1/waku_protocol, ../../../protocol/v2/waku_protocol, nimcrypto/[sysrand, hmac, sha2, pbkdf2], - ../../v0/rpc/[rpc_types, hexstrings, key_storage] + ../../v1/rpc/[rpc_types, hexstrings, key_storage] from stew/byteutils import hexToSeqByte, hexToByteArray diff --git a/waku/node/v2/wakunode.nim b/waku/node/v2/wakunode.nim index cedcd679d..c1883a4d3 100644 --- a/waku/node/v2/wakunode.nim +++ b/waku/node/v2/wakunode.nim @@ -5,7 +5,7 @@ import eth/p2p/[discovery, enode, peer_pool, bootnodes, whispernodes], eth/p2p/rlpx_protocols/[whisper_protocol, waku_protocol, waku_bridge], # TODO remove me - ../v0/rpc/[wakusim, key_storage], + ../v1/rpc/[wakusim, key_storage], ../../vendor/nim-libp2p/libp2p/standard_setup, ../../vendor/nim-libp2p/libp2p/multiaddress, ../../vendor/nim-libp2p/libp2p/crypto/crypto, diff --git a/waku/protocol/v1/waku_bridge.nim b/waku/protocol/v1/waku_bridge.nim new file mode 100644 index 000000000..3227c242d --- /dev/null +++ b/waku/protocol/v1/waku_bridge.nim @@ -0,0 +1,17 @@ +# +# Waku - Whisper Bridge +# (c) Copyright 2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) +# + +import + eth/p2p, + eth/p2p/rlpx_protocols/whisper_protocol, + ./waku_protocol + +proc shareMessageQueue*(node: EthereumNode) = + node.protocolState(Waku).queue = node.protocolState(Whisper).queue diff --git a/waku/protocol/v1/waku_mail.nim b/waku/protocol/v1/waku_mail.nim new file mode 100644 index 000000000..535d387fc --- /dev/null +++ b/waku/protocol/v1/waku_mail.nim @@ -0,0 +1,86 @@ +# +# Waku Mail Client & Server +# (c) Copyright 2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) +# +import + chronos, + eth/[p2p, async_utils], + ./waku_protocol + +const + requestCompleteTimeout = chronos.seconds(5) + +type + Cursor = seq[byte] + + MailRequest* = object + lower*: uint32 ## Unix timestamp; oldest requested envelope's creation time + upper*: uint32 ## Unix timestamp; newest requested envelope's creation time + bloom*: seq[byte] ## Bloom filter to apply on the envelopes + limit*: uint32 ## Maximum amount of envelopes to return + cursor*: Cursor ## Optional cursor + +proc requestMail*(node: EthereumNode, peerId: NodeId, request: MailRequest, + symKey: SymKey, requests = 10): Future[Option[Cursor]] {.async.} = + ## Send p2p mail request and check request complete. + ## If result is none, and error occured. If result is a none empty cursor, + ## more envelopes are available. + # TODO: Perhaps don't go the recursive route or could use the actual response + # proc to implement this (via a handler) and store the necessary data in the + # WakuPeer object. + # TODO: Several requestMail calls in parallel can create issues with handling + # the wrong response to a request. Can additionaly check the requestId but + # that would only solve it half. Better to use the requestResponse mechanism. + + # TODO: move this check out of requestMail? + let peer = node.getPeer(peerId, Waku) + if not peer.isSome(): + error "Invalid peer" + return result + elif not peer.get().state(Waku).trusted: + return result + + var writer = initRlpWriter() + writer.append(request) + let payload = writer.finish() + let data = encode(Payload(payload: payload, symKey: some(symKey))) + if not data.isSome(): + error "Encoding of payload failed" + return result + + # TODO: should this envelope be valid in terms of ttl, PoW, etc.? + let env = Envelope(expiry:0, ttl: 0, data: data.get(), nonce: 0) + # Send the request + traceAsyncErrors peer.get().p2pRequest(env) + + # Wait for the Request Complete packet + var f = peer.get().nextMsg(Waku.p2pRequestComplete) + if await f.withTimeout(requestCompleteTimeout): + let response = f.read() + # TODO: I guess the idea is to check requestId (Hash) also? + let requests = requests - 1 + # If there is cursor data, do another request + if response.cursor.len > 0 and requests > 0: + var newRequest = request + newRequest.cursor = response.cursor + return await requestMail(node, peerId, newRequest, symKey, requests) + else: + return some(response.cursor) + else: + error "p2pRequestComplete timeout" + return result + +proc p2pRequestHandler(peer: Peer, envelope: Envelope) = + # Mail server p2p request implementation + discard + +proc enableMailServer*(node: EthereumNode, customHandler: P2PRequestHandler) = + node.protocolState(Waku).p2pRequestHandler = customHandler + +proc enableMailServer*(node: EthereumNode) = + node.protocolState(Waku).p2pRequestHandler = p2pRequestHandler diff --git a/waku/protocol/v1/waku_protocol.nim b/waku/protocol/v1/waku_protocol.nim new file mode 100644 index 000000000..3a1fbe672 --- /dev/null +++ b/waku/protocol/v1/waku_protocol.nim @@ -0,0 +1,649 @@ +# +# Waku +# (c) Copyright 2018-2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) +# + +## Waku +## ******* +## +## Waku is a fork of Whisper. +## +## Waku is a gossip protocol that synchronizes a set of messages across nodes +## with attention given to sender and recipient anonymitiy. Messages are +## categorized by a topic and stay alive in the network based on a time-to-live +## measured in seconds. Spam prevention is based on proof-of-work, where large +## or long-lived messages must spend more work. +## +## Implementation should be according to Waku specification defined here: +## https://github.com/vacp2p/specs/blob/master/waku/waku.md +## +## Example usage +## ---------- +## First an `EthereumNode` needs to be created, either with all capabilities set +## or with specifically the Waku capability set. +## The latter can be done like this: +## +## .. code-block::nim +## var node = newEthereumNode(keypair, address, netId, nil, +## addAllCapabilities = false) +## node.addCapability Waku +## +## Now calls such as ``postMessage`` and ``subscribeFilter`` can be done. +## However, they only make real sense after ``connectToNetwork`` was started. As +## else there will be no peers to send and receive messages from. + +import + options, tables, times, chronos, chronicles, metrics, + eth/[keys, async_utils, p2p], eth/p2p/rlpx_protocols/whisper/whisper_types, + eth/trie/trie_defs + +export + whisper_types + +logScope: + topics = "waku" + +declarePublicCounter dropped_low_pow_envelopes, + "Dropped envelopes because of too low PoW" +declarePublicCounter dropped_too_large_envelopes, + "Dropped envelopes because larger than maximum allowed size" +declarePublicCounter dropped_bloom_filter_mismatch_envelopes, + "Dropped envelopes because not matching with bloom filter" +declarePublicCounter dropped_topic_mismatch_envelopes, + "Dropped envelopes because of not matching topics" +declarePublicCounter dropped_duplicate_envelopes, + "Dropped duplicate envelopes" + +const + defaultQueueCapacity = 2048 + wakuVersion* = 1 ## Waku version. + wakuVersionStr* = $wakuVersion ## Waku version. + defaultMinPow* = 0.2'f64 ## The default minimum PoW requirement for this node. + defaultMaxMsgSize* = 1024'u32 * 1024'u32 ## The current default and max + ## message size. This can never be larger than the maximum RLPx message size. + messageInterval* = chronos.milliseconds(300) ## Interval at which messages are + ## send to peers, in ms. + pruneInterval* = chronos.milliseconds(1000) ## Interval at which message + ## queue is pruned, in ms. + topicInterestMax = 10000 + +type + WakuConfig* = object + powRequirement*: float64 + bloom*: Option[Bloom] + isLightNode*: bool + maxMsgSize*: uint32 + confirmationsEnabled*: bool + rateLimits*: Option[RateLimits] + topics*: Option[seq[Topic]] + + WakuPeer = ref object + initialized: bool # when successfully completed the handshake + powRequirement*: float64 + bloom*: Bloom + isLightNode*: bool + trusted*: bool + topics*: Option[seq[Topic]] + received: HashSet[Hash] + + P2PRequestHandler* = proc(peer: Peer, envelope: Envelope) {.gcsafe.} + + WakuNetwork = ref object + queue*: ref Queue + filters*: Filters + config*: WakuConfig + p2pRequestHandler*: P2PRequestHandler + + RateLimits* = object + # TODO: uint or specifically uint32? + limitIp*: uint + limitPeerId*: uint + limitTopic*: uint + + StatusOptions* = object + powRequirement*: Option[(float64)] + bloomFilter*: Option[Bloom] + lightNode*: Option[bool] + confirmationsEnabled*: Option[bool] + rateLimits*: Option[RateLimits] + topicInterest*: Option[seq[Topic]] + + KeyKind* = enum + powRequirementKey, + bloomFilterKey, + lightNodeKey, + confirmationsEnabledKey, + rateLimitsKey, + topicInterestKey + +template countSomeFields*(x: StatusOptions): int = + var count = 0 + for f in fields(x): + if f.isSome(): + inc count + count + +proc append*(rlpWriter: var RlpWriter, value: StatusOptions) = + var list = initRlpList(countSomeFields(value)) + if value.powRequirement.isSome(): + list.append((powRequirementKey, cast[uint64](value.powRequirement.get()))) + if value.bloomFilter.isSome(): + list.append((bloomFilterKey, @(value.bloomFilter.get()))) + if value.lightNode.isSome(): + list.append((lightNodeKey, value.lightNode.get())) + if value.confirmationsEnabled.isSome(): + list.append((confirmationsEnabledKey, value.confirmationsEnabled.get())) + if value.rateLimits.isSome(): + list.append((rateLimitsKey, value.rateLimits.get())) + if value.topicInterest.isSome(): + list.append((topicInterestKey, value.topicInterest.get())) + + let bytes = list.finish() + + rlpWriter.append(rlpFromBytes(bytes)) + +proc read*(rlp: var Rlp, T: typedesc[StatusOptions]): T = + if not rlp.isList(): + raise newException(RlpTypeMismatch, + "List expected, but the source RLP is not a list.") + + let sz = rlp.listLen() + # We already know that we are working with a list + doAssert rlp.enterList() + for i in 0 ..< sz: + rlp.tryEnterList() + + var k: KeyKind + try: + k = rlp.read(KeyKind) + except RlpTypeMismatch: + # skip unknown keys and their value + rlp.skipElem() + rlp.skipElem() + continue + + case k + of powRequirementKey: + let pow = rlp.read(uint64) + result.powRequirement = some(cast[float64](pow)) + of bloomFilterKey: + let bloom = rlp.read(seq[byte]) + if bloom.len != bloomSize: + raise newException(UselessPeerError, "Bloomfilter size mismatch") + var bloomFilter: Bloom + bloomFilter.bytesCopy(bloom) + result.bloomFilter = some(bloomFilter) + of lightNodeKey: + result.lightNode = some(rlp.read(bool)) + of confirmationsEnabledKey: + result.confirmationsEnabled = some(rlp.read(bool)) + of rateLimitsKey: + result.rateLimits = some(rlp.read(RateLimits)) + of topicInterestKey: + result.topicInterest = some(rlp.read(seq[Topic])) + +proc allowed*(msg: Message, config: WakuConfig): bool = + # Check max msg size, already happens in RLPx but there is a specific waku + # max msg size which should always be < RLPx max msg size + if msg.size > config.maxMsgSize: + dropped_too_large_envelopes.inc() + warn "Message size too large", size = msg.size + return false + + if msg.pow < config.powRequirement: + dropped_low_pow_envelopes.inc() + warn "Message PoW too low", pow = msg.pow, minPow = config.powRequirement + return false + + if config.topics.isSome(): + if msg.env.topic notin config.topics.get(): + dropped_topic_mismatch_envelopes.inc() + warn "Message topic does not match Waku topic list" + return false + else: + if config.bloom.isSome() and not bloomFilterMatch(config.bloom.get(), msg.bloom): + dropped_bloom_filter_mismatch_envelopes.inc() + warn "Message does not match node bloom filter" + return false + + return true + +proc run(peer: Peer) {.gcsafe, async.} +proc run(node: EthereumNode, network: WakuNetwork) {.gcsafe, async.} + +proc initProtocolState*(network: WakuNetwork, node: EthereumNode) {.gcsafe.} = + new(network.queue) + network.queue[] = initQueue(defaultQueueCapacity) + network.filters = initTable[string, Filter]() + network.config.bloom = some(fullBloom()) + network.config.powRequirement = defaultMinPow + network.config.isLightNode = false + # RateLimits and confirmations are not yet implemented so we set confirmations + # to false and we don't pass RateLimits at all. + network.config.confirmationsEnabled = false + network.config.rateLimits = none(RateLimits) + network.config.maxMsgSize = defaultMaxMsgSize + network.config.topics = none(seq[Topic]) + asyncCheck node.run(network) + +p2pProtocol Waku(version = wakuVersion, + rlpxName = "waku", + peerState = WakuPeer, + networkState = WakuNetwork): + + onPeerConnected do (peer: Peer): + trace "onPeerConnected Waku" + let + wakuNet = peer.networkState + wakuPeer = peer.state + + let options = StatusOptions( + powRequirement: some(wakuNet.config.powRequirement), + bloomFilter: wakuNet.config.bloom, + lightNode: some(wakuNet.config.isLightNode), + confirmationsEnabled: some(wakuNet.config.confirmationsEnabled), + rateLimits: wakuNet.config.rateLimits, + topicInterest: wakuNet.config.topics) + + let m = await peer.status(options, + timeout = chronos.milliseconds(5000)) + + wakuPeer.powRequirement = m.options.powRequirement.get(defaultMinPow) + wakuPeer.bloom = m.options.bloomFilter.get(fullBloom()) + + wakuPeer.isLightNode = m.options.lightNode.get(false) + if wakuPeer.isLightNode and wakuNet.config.isLightNode: + # No sense in connecting two light nodes so we disconnect + raise newException(UselessPeerError, "Two light nodes connected") + + wakuPeer.topics = m.options.topicInterest + if wakuPeer.topics.isSome(): + if wakuPeer.topics.get().len > topicInterestMax: + raise newException(UselessPeerError, "Topic-interest is too large") + if wakuNet.config.topics.isSome(): + raise newException(UselessPeerError, + "Two Waku nodes with topic-interest connected") + + wakuPeer.received.init() + wakuPeer.trusted = false + wakuPeer.initialized = true + + # No timer based queue processing for a light node. + if not wakuNet.config.isLightNode: + traceAsyncErrors peer.run() + + debug "Waku peer initialized", peer + + handshake: + proc status(peer: Peer, options: StatusOptions) + + proc messages(peer: Peer, envelopes: openarray[Envelope]) = + if not peer.state.initialized: + warn "Handshake not completed yet, discarding messages" + return + + for envelope in envelopes: + # check if expired or in future, or ttl not 0 + if not envelope.valid(): + warn "Expired or future timed envelope", peer + # disconnect from peers sending bad envelopes + # await peer.disconnect(SubprotocolReason) + continue + + let msg = initMessage(envelope) + if not msg.allowed(peer.networkState.config): + # disconnect from peers sending bad envelopes + # await peer.disconnect(SubprotocolReason) + continue + + # This peer send this message thus should not receive it again. + # If this peer has the message in the `received` set already, this means + # it was either already received here from this peer or send to this peer. + # Either way it will be in our queue already (and the peer should know + # this) and this peer is sending duplicates. + # Note: geth does not check if a peer has send a message to them before + # broadcasting this message. This too is seen here as a duplicate message + # (see above comment). If we want to seperate these cases (e.g. when peer + # rating), then we have to add a "peer.state.send" HashSet. + # Note: it could also be a race between the arrival of a message send by + # this node to a peer and that same message arriving from that peer (after + # it was received from another peer) here. + if peer.state.received.containsOrIncl(msg.hash): + dropped_duplicate_envelopes.inc() + trace "Peer sending duplicate messages", peer, hash = $msg.hash + # await peer.disconnect(SubprotocolReason) + continue + + # This can still be a duplicate message, but from another peer than + # the peer who send the message. + if peer.networkState.queue[].add(msg): + # notify filters of this message + peer.networkState.filters.notify(msg) + + nextID 22 + + proc statusOptions(peer: Peer, options: StatusOptions) = + if not peer.state.initialized: + warn "Handshake not completed yet, discarding statusOptions" + return + + if options.topicInterest.isSome(): + peer.state.topics = options.topicInterest + elif options.bloomFilter.isSome(): + peer.state.bloom = options.bloomFilter.get() + peer.state.topics = none(seq[Topic]) + + if options.powRequirement.isSome(): + peer.state.powRequirement = options.powRequirement.get() + + if options.lightNode.isSome(): + peer.state.isLightNode = options.lightNode.get() + + nextID 126 + + proc p2pRequest(peer: Peer, envelope: Envelope) = + if not peer.networkState.p2pRequestHandler.isNil(): + peer.networkState.p2pRequestHandler(peer, envelope) + + proc p2pMessage(peer: Peer, envelopes: openarray[Envelope]) = + if peer.state.trusted: + # when trusted we can bypass any checks on envelope + for envelope in envelopes: + let msg = Message(env: envelope, isP2P: true) + peer.networkState.filters.notify(msg) + + # Following message IDs are not part of EIP-627, but are added and used by + # the Status application, we ignore them for now. + nextID 11 + proc batchAcknowledged(peer: Peer) = discard + proc messageResponse(peer: Peer) = discard + + nextID 123 + requestResponse: + proc p2pSyncRequest(peer: Peer) = discard + proc p2pSyncResponse(peer: Peer) = discard + + + proc p2pRequestComplete(peer: Peer, requestId: Hash, lastEnvelopeHash: Hash, + cursor: seq[byte]) = discard + # TODO: + # In the current specification the parameters are not wrapped in a regular + # envelope as is done for the P2P Request packet. If we could alter this in + # the spec it would be a cleaner separation between Waku and Mail server / + # client. + # Also, if a requestResponse block is used, a reqestId will automatically + # be added by the protocol DSL. + # However the requestResponse block in combination with p2pRequest cannot be + # used due to the unfortunate fact that the packet IDs are not consecutive, + # and nextID is not recognized in between these. The nextID behaviour could + # be fixed, however it would be cleaner if the specification could be + # changed to have these IDs to be consecutive. + +# 'Runner' calls --------------------------------------------------------------- + +proc processQueue(peer: Peer) = + # Send to peer all valid and previously not send envelopes in the queue. + var + envelopes: seq[Envelope] = @[] + wakuPeer = peer.state(Waku) + wakuNet = peer.networkState(Waku) + + for message in wakuNet.queue.items: + if wakuPeer.received.contains(message.hash): + # trace "message was already send to peer", hash = $message.hash, peer + continue + + if message.pow < wakuPeer.powRequirement: + trace "Message PoW too low for peer", pow = message.pow, + powReq = wakuPeer.powRequirement + continue + + if wakuPeer.topics.isSome(): + if message.env.topic notin wakuPeer.topics.get(): + trace "Message does not match topics list" + continue + else: + if not bloomFilterMatch(wakuPeer.bloom, message.bloom): + trace "Message does not match peer bloom filter" + continue + + trace "Adding envelope" + envelopes.add(message.env) + wakuPeer.received.incl(message.hash) + + if envelopes.len() > 0: + trace "Sending envelopes", amount=envelopes.len + # Ignore failure of sending messages, this could occur when the connection + # gets dropped + traceAsyncErrors peer.messages(envelopes) + +proc run(peer: Peer) {.async.} = + while peer.connectionState notin {Disconnecting, Disconnected}: + peer.processQueue() + await sleepAsync(messageInterval) + +proc pruneReceived(node: EthereumNode) {.raises: [].} = + if node.peerPool != nil: # XXX: a bit dirty to need to check for this here ... + var wakuNet = node.protocolState(Waku) + + for peer in node.protocolPeers(Waku): + if not peer.initialized: + continue + + # NOTE: Perhaps alter the queue prune call to keep track of a HashSet + # of pruned messages (as these should be smaller), and diff this with + # the received sets. + peer.received = intersection(peer.received, wakuNet.queue.itemHashes) + +proc run(node: EthereumNode, network: WakuNetwork) {.async.} = + while true: + # prune message queue every second + # TTL unit is in seconds, so this should be sufficient? + network.queue[].prune() + # pruning the received sets is not necessary for correct workings + # but simply from keeping the sets growing indefinitely + node.pruneReceived() + await sleepAsync(pruneInterval) + +# Private EthereumNode calls --------------------------------------------------- + +proc sendP2PMessage(node: EthereumNode, peerId: NodeId, + envelopes: openarray[Envelope]): bool = + for peer in node.peers(Waku): + if peer.remote.id == peerId: + asyncCheck peer.p2pMessage(envelopes) + return true + +proc queueMessage(node: EthereumNode, msg: Message): bool = + + var wakuNet = node.protocolState(Waku) + # We have to do the same checks here as in the messages proc not to leak + # any information that the message originates from this node. + if not msg.allowed(wakuNet.config): + return false + + trace "Adding message to queue", hash = $msg.hash + if wakuNet.queue[].add(msg): + # Also notify our own filters of the message we are sending, + # e.g. msg from local Dapp to Dapp + wakuNet.filters.notify(msg) + + return true + +# Public EthereumNode calls ---------------------------------------------------- + +proc postMessage*(node: EthereumNode, pubKey = none[PublicKey](), + symKey = none[SymKey](), src = none[PrivateKey](), + ttl: uint32, topic: Topic, payload: seq[byte], + padding = none[seq[byte]](), powTime = 1'f, + powTarget = defaultMinPow, + targetPeer = none[NodeId]()): bool = + ## Post a message on the message queue which will be processed at the + ## next `messageInterval`. + ## + ## NOTE: This call allows a post without encryption. If encryption is + ## mandatory it should be enforced a layer up + let payload = encode(Payload(payload: payload, src: src, dst: pubKey, + symKey: symKey, padding: padding)) + if payload.isSome(): + var env = Envelope(expiry:epochTime().uint32 + ttl, + ttl: ttl, topic: topic, data: payload.get(), nonce: 0) + + # Allow lightnode to post only direct p2p messages + if targetPeer.isSome(): + return node.sendP2PMessage(targetPeer.get(), [env]) + else: + # non direct p2p message can not have ttl of 0 + if env.ttl == 0: + return false + var msg = initMessage(env, powCalc = false) + # XXX: make this non blocking or not? + # In its current blocking state, it could be noticed by a peer that no + # messages are send for a while, and thus that mining PoW is done, and + # that next messages contains a message originated from this peer + # zah: It would be hard to execute this in a background thread at the + # moment. We'll need a way to send custom "tasks" to the async message + # loop (e.g. AD2 support for AsyncChannels). + if not msg.sealEnvelope(powTime, powTarget): + return false + + # need to check expiry after mining PoW + if not msg.env.valid(): + return false + + result = node.queueMessage(msg) + + # Allows light nodes to post via untrusted messages packet. + # Queue gets processed immediatly as the node sends only its own messages, + # so the privacy ship has already sailed anyhow. + # TODO: + # - Could be still a concern in terms of efficiency, if multiple messages + # need to be send. + # - For Waku Mode, the checks in processQueue are rather useless as the + # idea is to connect only to 1 node? Also refactor in that case. + if node.protocolState(Waku).config.isLightNode: + for peer in node.peers(Waku): + peer.processQueue() + else: + error "Encoding of payload failed" + return false + +proc subscribeFilter*(node: EthereumNode, filter: Filter, + handler:FilterMsgHandler = nil): string = + ## Initiate a filter for incoming/outgoing messages. Messages can be + ## retrieved with the `getFilterMessages` call or with a provided + ## `FilterMsgHandler`. + ## + ## NOTE: This call allows for a filter without decryption. If encryption is + ## mandatory it should be enforced a layer up. + return node.protocolState(Waku).filters.subscribeFilter(filter, handler) + +proc unsubscribeFilter*(node: EthereumNode, filterId: string): bool = + ## Remove a previously subscribed filter. + var filter: Filter + return node.protocolState(Waku).filters.take(filterId, filter) + +proc getFilterMessages*(node: EthereumNode, filterId: string): seq[ReceivedMessage] = + ## Get all the messages currently in the filter queue. This will reset the + ## filter message queue. + return node.protocolState(Waku).filters.getFilterMessages(filterId) + +proc filtersToBloom*(node: EthereumNode): Bloom = + ## Returns the bloom filter of all topics of all subscribed filters. + return node.protocolState(Waku).filters.toBloom() + +proc setPowRequirement*(node: EthereumNode, powReq: float64) {.async.} = + ## Sets the PoW requirement for this node, will also send + ## this new PoW requirement to all connected peers. + ## + ## Failures when sending messages to peers will not be reported. + # NOTE: do we need a tolerance of old PoW for some time? + node.protocolState(Waku).config.powRequirement = powReq + var futures: seq[Future[void]] = @[] + let list = StatusOptions(powRequirement: some(powReq)) + for peer in node.peers(Waku): + futures.add(peer.statusOptions(list)) + + # Exceptions from sendMsg will not be raised + await allFutures(futures) + +proc setBloomFilter*(node: EthereumNode, bloom: Bloom) {.async.} = + ## Sets the bloom filter for this node, will also send + ## this new bloom filter to all connected peers. + ## + ## Failures when sending messages to peers will not be reported. + # NOTE: do we need a tolerance of old bloom filter for some time? + node.protocolState(Waku).config.bloom = some(bloom) + # reset topics + node.protocolState(Waku).config.topics = none(seq[Topic]) + + var futures: seq[Future[void]] = @[] + let list = StatusOptions(bloomFilter: some(bloom)) + for peer in node.peers(Waku): + futures.add(peer.statusOptions(list)) + + # Exceptions from sendMsg will not be raised + await allFutures(futures) + +proc setTopicInterest*(node: EthereumNode, topics: seq[Topic]): + Future[bool] {.async.} = + if topics.len > topicInterestMax: + return false + + node.protocolState(Waku).config.topics = some(topics) + + var futures: seq[Future[void]] = @[] + let list = StatusOptions(topicInterest: some(topics)) + for peer in node.peers(Waku): + futures.add(peer.statusOptions(list)) + + # Exceptions from sendMsg will not be raised + await allFutures(futures) + + return true + +proc setMaxMessageSize*(node: EthereumNode, size: uint32): bool = + ## Set the maximum allowed message size. + ## Can not be set higher than ``defaultMaxMsgSize``. + if size > defaultMaxMsgSize: + warn "size > defaultMaxMsgSize" + return false + node.protocolState(Waku).config.maxMsgSize = size + return true + +proc setPeerTrusted*(node: EthereumNode, peerId: NodeId): bool = + ## Set a connected peer as trusted. + for peer in node.peers(Waku): + if peer.remote.id == peerId: + peer.state(Waku).trusted = true + return true + +proc setLightNode*(node: EthereumNode, isLightNode: bool) {.async.} = + ## Set this node as a Waku light node. + node.protocolState(Waku).config.isLightNode = isLightNode +# TODO: Add starting/stopping of `processQueue` loop depending on value of isLightNode. + var futures: seq[Future[void]] = @[] + let list = StatusOptions(lightNode: some(isLightNode)) + for peer in node.peers(Waku): + futures.add(peer.statusOptions(list)) + + # Exceptions from sendMsg will not be raised + await allFutures(futures) + +proc configureWaku*(node: EthereumNode, config: WakuConfig) = + ## Apply a Waku configuration. + ## + ## NOTE: Should be run before connection is made with peers as some + ## of the settings are only communicated at peer handshake. + node.protocolState(Waku).config = config + +proc resetMessageQueue*(node: EthereumNode) = + ## Full reset of the message queue. + ## + ## NOTE: Not something that should be run in normal circumstances. + node.protocolState(Waku).queue[] = initQueue(defaultQueueCapacity) From aa7f65bca09fd35a2d2e774bbc18aeac2674e275 Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 1 May 2020 15:36:20 +0200 Subject: [PATCH 7/9] Add to tests to test_waku_connect and add test_waku_config --- tests/all_tests.nim | 4 +- tests/test_waku_config.nim | 64 +++++++ tests/test_waku_connect.nim | 344 ++++++++++++++++++++++++++++++++++-- 3 files changed, 392 insertions(+), 20 deletions(-) create mode 100644 tests/test_waku_config.nim diff --git a/tests/all_tests.nim b/tests/all_tests.nim index 046f7bedc..ab0542d47 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -1,5 +1,7 @@ import ./test_waku_connect, + ./test_waku_config, ./test_waku_bridge, ./test_waku_mail, - ./test_rpc_waku \ No newline at end of file + ./test_rpc_waku + \ No newline at end of file diff --git a/tests/test_waku_config.nim b/tests/test_waku_config.nim new file mode 100644 index 000000000..fe3d2223a --- /dev/null +++ b/tests/test_waku_config.nim @@ -0,0 +1,64 @@ +# +# Waku +# (c) Copyright 2020 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) + +import + sequtils, options, unittest, times, + ../waku/protocol/v1/waku_protocol + +suite "Waku envelope validation": + test "should validate and allow envelope according to config": + let ttl = 1'u32 + let topic = [byte 1, 2, 3, 4] + let config = WakuConfig(powRequirement: 0, bloom: some(topic.topicBloom()), + isLightNode: false, maxMsgSize: defaultMaxMsgSize) + + let env = Envelope(expiry:epochTime().uint32 + ttl, ttl: ttl, topic: topic, + data: repeat(byte 9, 256), nonce: 0) + check env.valid() + + let msg = initMessage(env) + check msg.allowed(config) + + test "should invalidate envelope due to ttl 0": + let ttl = 0'u32 + let topic = [byte 1, 2, 3, 4] + + let env = Envelope(expiry:epochTime().uint32 + ttl, ttl: ttl, topic: topic, + data: repeat(byte 9, 256), nonce: 0) + check env.valid() == false + + test "should invalidate envelope due to expired": + let ttl = 1'u32 + let topic = [byte 1, 2, 3, 4] + + let env = Envelope(expiry:epochTime().uint32, ttl: ttl, topic: topic, + data: repeat(byte 9, 256), nonce: 0) + check env.valid() == false + + test "should invalidate envelope due to in the future": + let ttl = 1'u32 + let topic = [byte 1, 2, 3, 4] + + # there is currently a 2 second tolerance, hence the + 3 + let env = Envelope(expiry:epochTime().uint32 + ttl + 3, ttl: ttl, + topic: topic, data: repeat(byte 9, 256), nonce: 0) + check env.valid() == false + + test "should not allow envelope due to bloom filter": + let topic = [byte 1, 2, 3, 4] + let wrongTopic = [byte 9, 8, 7, 6] + let config = WakuConfig(powRequirement: 0, + bloom: some(wrongTopic.topicBloom()), + isLightNode: false, maxMsgSize: defaultMaxMsgSize) + + let env = Envelope(expiry:100000 , ttl: 30, topic: topic, + data: repeat(byte 9, 256), nonce: 0) + + let msg = initMessage(env) + check msg.allowed(config) == false diff --git a/tests/test_waku_connect.nim b/tests/test_waku_connect.nim index 6d0f18cde..b096a47e2 100644 --- a/tests/test_waku_connect.nim +++ b/tests/test_waku_connect.nim @@ -17,6 +17,10 @@ const waitInterval = messageInterval + 150.milliseconds conditionTimeoutMs = 3000 +proc resetMessageQueues(nodes: varargs[EthereumNode]) = + for node in nodes: + node.resetMessageQueue() + # check on a condition until true or return a future containing false # if timeout expires first proc eventually(timeout: int, condition: proc(): bool {.gcsafe.}): Future[bool] = @@ -28,8 +32,6 @@ proc eventually(timeout: int, condition: proc(): bool {.gcsafe.}): Future[bool] return await f return withTimeout(wrappedCondition(), timeout) -# TODO: Just repeat all the test_shh_connect tests here that are applicable or -# have some commonly shared test code for both protocols. suite "Waku connections": asyncTest "Waku connections": var @@ -56,6 +58,327 @@ suite "Waku connections": p2.isNil == false p3.isNil == false + asyncTest "Filters with encryption and signing": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let encryptKeyPair = KeyPair.random()[] + let signKeyPair = KeyPair.random()[] + var symKey: SymKey + let topic = [byte 0x12, 0, 0, 0] + var filters: seq[string] = @[] + var payloads = [repeat(byte 1, 10), repeat(byte 2, 10), + repeat(byte 3, 10), repeat(byte 4, 10)] + var futures = [newFuture[int](), newFuture[int](), + newFuture[int](), newFuture[int]()] + + proc handler1(msg: ReceivedMessage) = + var count {.global.}: int + check msg.decoded.payload == payloads[0] or msg.decoded.payload == payloads[1] + count += 1 + if count == 2: futures[0].complete(1) + proc handler2(msg: ReceivedMessage) = + check msg.decoded.payload == payloads[1] + futures[1].complete(1) + proc handler3(msg: ReceivedMessage) = + var count {.global.}: int + check msg.decoded.payload == payloads[2] or msg.decoded.payload == payloads[3] + count += 1 + if count == 2: futures[2].complete(1) + proc handler4(msg: ReceivedMessage) = + check msg.decoded.payload == payloads[3] + futures[3].complete(1) + + # Filters + # filter for encrypted asym + filters.add(node1.subscribeFilter(initFilter(privateKey = some(encryptKeyPair.seckey), + topics = @[topic]), handler1)) + # filter for encrypted asym + signed + filters.add(node1.subscribeFilter(initFilter(some(signKeyPair.pubkey), + privateKey = some(encryptKeyPair.seckey), + topics = @[topic]), handler2)) + # filter for encrypted sym + filters.add(node1.subscribeFilter(initFilter(symKey = some(symKey), + topics = @[topic]), handler3)) + # filter for encrypted sym + signed + filters.add(node1.subscribeFilter(initFilter(some(signKeyPair.pubkey), + symKey = some(symKey), + topics = @[topic]), handler4)) + # Messages + check: + # encrypted asym + node2.postMessage(some(encryptKeyPair.pubkey), ttl = safeTTL, + topic = topic, payload = payloads[0]) == true + # encrypted asym + signed + node2.postMessage(some(encryptKeyPair.pubkey), + src = some(signKeyPair.seckey), ttl = safeTTL, + topic = topic, payload = payloads[1]) == true + # encrypted sym + node2.postMessage(symKey = some(symKey), ttl = safeTTL, topic = topic, + payload = payloads[2]) == true + # encrypted sym + signed + node2.postMessage(symKey = some(symKey), + src = some(signKeyPair.seckey), + ttl = safeTTL, topic = topic, + payload = payloads[3]) == true + + node2.protocolState(Waku).queue.items.len == 4 + + check: + await allFutures(futures).withTimeout(waitInterval) + node1.protocolState(Waku).queue.items.len == 4 + + for filter in filters: + check node1.unsubscribeFilter(filter) == true + + asyncTest "Filters with topics": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic1 = [byte 0x12, 0, 0, 0] + let topic2 = [byte 0x34, 0, 0, 0] + var payloads = [repeat(byte 0, 10), repeat(byte 1, 10)] + var futures = [newFuture[int](), newFuture[int]()] + proc handler1(msg: ReceivedMessage) = + check msg.decoded.payload == payloads[0] + futures[0].complete(1) + proc handler2(msg: ReceivedMessage) = + check msg.decoded.payload == payloads[1] + futures[1].complete(1) + + var filter1 = node1.subscribeFilter(initFilter(topics = @[topic1]), handler1) + var filter2 = node1.subscribeFilter(initFilter(topics = @[topic2]), handler2) + + check: + node2.postMessage(ttl = safeTTL + 1, topic = topic1, + payload = payloads[0]) == true + node2.postMessage(ttl = safeTTL, topic = topic2, + payload = payloads[1]) == true + node2.protocolState(Waku).queue.items.len == 2 + + await allFutures(futures).withTimeout(waitInterval) + node1.protocolState(Waku).queue.items.len == 2 + + node1.unsubscribeFilter(filter1) == true + node1.unsubscribeFilter(filter2) == true + + asyncTest "Filters with PoW": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0x12, 0, 0, 0] + var payload = repeat(byte 0, 10) + var futures = [newFuture[int](), newFuture[int]()] + proc handler1(msg: ReceivedMessage) = + check msg.decoded.payload == payload + futures[0].complete(1) + proc handler2(msg: ReceivedMessage) = + check msg.decoded.payload == payload + futures[1].complete(1) + + var filter1 = node1.subscribeFilter(initFilter(topics = @[topic], powReq = 0), + handler1) + var filter2 = node1.subscribeFilter(initFilter(topics = @[topic], + powReq = 1_000_000), handler2) + + check: + node2.postMessage(ttl = safeTTL, topic = topic, payload = payload) == true + + (await futures[0].withTimeout(waitInterval)) == true + (await futures[1].withTimeout(waitInterval)) == false + node1.protocolState(Waku).queue.items.len == 1 + + node1.unsubscribeFilter(filter1) == true + node1.unsubscribeFilter(filter2) == true + + asyncTest "Filters with queues": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0, 0, 0, 0] + let payload = repeat(byte 0, 10) + + var filter = node1.subscribeFilter(initFilter(topics = @[topic])) + for i in countdown(10, 1): + check node2.postMessage(ttl = safeTTL, topic = topic, + payload = payload) == true + + await sleepAsync(waitInterval) + check: + node1.getFilterMessages(filter).len() == 10 + node1.getFilterMessages(filter).len() == 0 + node1.unsubscribeFilter(filter) == true + + asyncTest "Local filter notify": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0, 0, 0, 0] + + var filter = node1.subscribeFilter(initFilter(topics = @[topic])) + check: + node1.postMessage(ttl = safeTTL, topic = topic, + payload = repeat(byte 4, 10)) == true + node1.getFilterMessages(filter).len() == 1 + node1.unsubscribeFilter(filter) == true + + asyncTest "Bloomfilter blocking": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let sendTopic1 = [byte 0x12, 0, 0, 0] + let sendTopic2 = [byte 0x34, 0, 0, 0] + let filterTopics = @[[byte 0x34, 0, 0, 0],[byte 0x56, 0, 0, 0]] + let payload = repeat(byte 0, 10) + var f: Future[int] = newFuture[int]() + proc handler(msg: ReceivedMessage) = + check msg.decoded.payload == payload + f.complete(1) + var filter = node1.subscribeFilter(initFilter(topics = filterTopics), handler) + await node1.setBloomFilter(node1.filtersToBloom()) + + check: + node2.postMessage(ttl = safeTTL, topic = sendTopic1, + payload = payload) == true + node2.protocolState(Waku).queue.items.len == 1 + + (await f.withTimeout(waitInterval)) == false + node1.protocolState(Waku).queue.items.len == 0 + + resetMessageQueues(node1, node2) + + f = newFuture[int]() + + check: + node2.postMessage(ttl = safeTTL, topic = sendTopic2, + payload = payload) == true + node2.protocolState(Waku).queue.items.len == 1 + + await f.withTimeout(waitInterval) + f.read() == 1 + node1.protocolState(Waku).queue.items.len == 1 + + node1.unsubscribeFilter(filter) == true + + await node1.setBloomFilter(fullBloom()) + + asyncTest "PoW blocking": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0, 0, 0, 0] + let payload = repeat(byte 0, 10) + + await node1.setPowRequirement(1_000_000) + check: + node2.postMessage(ttl = safeTTL, topic = topic, payload = payload) == true + node2.protocolState(Waku).queue.items.len == 1 + await sleepAsync(waitInterval) + check: + node1.protocolState(Waku).queue.items.len == 0 + + resetMessageQueues(node1, node2) + + await node1.setPowRequirement(0.0) + check: + node2.postMessage(ttl = safeTTL, topic = topic, payload = payload) == true + node2.protocolState(Waku).queue.items.len == 1 + await sleepAsync(waitInterval) + check: + node1.protocolState(Waku).queue.items.len == 1 + + asyncTest "Queue pruning": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0, 0, 0, 0] + let payload = repeat(byte 0, 10) + # We need a minimum TTL of 2 as when set to 1 there is a small chance that + # it is already expired after messageInterval due to rounding down of float + # to uint32 in postMessage() + let lowerTTL = 2'u32 # Lower TTL as we need to wait for messages to expire + for i in countdown(10, 1): + check node2.postMessage(ttl = lowerTTL, topic = topic, payload = payload) == true + check node2.protocolState(Waku).queue.items.len == 10 + + await sleepAsync(waitInterval) + check node1.protocolState(Waku).queue.items.len == 10 + + await sleepAsync(milliseconds((lowerTTL+1)*1000)) + check node1.protocolState(Waku).queue.items.len == 0 + check node2.protocolState(Waku).queue.items.len == 0 + + asyncTest "P2P post": + var node1 = setupTestNode(Waku) + var node2 = setupTestNode(Waku) + node2.startListening() + waitFor node1.peerPool.connectToNode(newNode(node2.toENode())) + + let topic = [byte 0, 0, 0, 0] + var f: Future[int] = newFuture[int]() + proc handler(msg: ReceivedMessage) = + check msg.decoded.payload == repeat(byte 4, 10) + f.complete(1) + + var filter = node1.subscribeFilter(initFilter(topics = @[topic], + allowP2P = true), handler) + check: + node1.setPeerTrusted(toNodeId(node2.keys.pubkey)) == true + node2.postMessage(ttl = 10, topic = topic, + payload = repeat(byte 4, 10), + targetPeer = some(toNodeId(node1.keys.pubkey))) == true + + await f.withTimeout(waitInterval) + f.read() == 1 + node1.protocolState(Waku).queue.items.len == 0 + node2.protocolState(Waku).queue.items.len == 0 + + node1.unsubscribeFilter(filter) == true + + asyncTest "Light node posting": + var ln = setupTestNode(Waku) + await ln.setLightNode(true) + var fn = setupTestNode(Waku) + fn.startListening() + await ln.peerPool.connectToNode(newNode(fn.toENode())) + + let topic = [byte 0, 0, 0, 0] + + check: + ln.peerPool.connectedNodes.len() == 1 + # normal post + ln.postMessage(ttl = safeTTL, topic = topic, + payload = repeat(byte 0, 10)) == true + ln.protocolState(Waku).queue.items.len == 1 + # TODO: add test on message relaying + + asyncTest "Connect two light nodes": + var ln1 = setupTestNode(Waku) + var ln2 = setupTestNode(Waku) + + await ln1.setLightNode(true) + await ln2.setLightNode(true) + + ln2.startListening() + let peer = await ln1.rlpxConnect(newNode(ln2.toENode())) + check peer.isNil == true + asyncTest "Waku set-topic-interest": var wakuTopicNode = setupTestNode(Waku) @@ -223,20 +546,3 @@ suite "Waku connections": await sleepAsync(waitInterval) check: wakuTopicNode.protocolState(Waku).queue.items.len == 2 - - asyncTest "Light node posting": - var ln = setupTestNode(Waku) - await ln.setLightNode(true) - var fn = setupTestNode(Waku) - fn.startListening() - await ln.peerPool.connectToNode(newNode(fn.toENode())) - - let topic = [byte 0, 0, 0, 0] - - check: - ln.peerPool.connectedNodes.len() == 1 - # normal post - ln.postMessage(ttl = safeTTL, topic = topic, - payload = repeat(byte 0, 10)) == true - ln.protocolState(Waku).queue.items.len == 1 - # TODO: add test on message relaying From 58b2a3caef5ac140815d636bc71e7b879e06a4a3 Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 1 May 2020 21:13:42 +0200 Subject: [PATCH 8/9] Add check for node in peerpool in P2P post test --- tests/test_waku_connect.nim | 57 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/tests/test_waku_connect.nim b/tests/test_waku_connect.nim index b096a47e2..1e8cce148 100644 --- a/tests/test_waku_connect.nim +++ b/tests/test_waku_connect.nim @@ -15,7 +15,7 @@ import const safeTTL = 5'u32 waitInterval = messageInterval + 150.milliseconds - conditionTimeoutMs = 3000 + conditionTimeoutMs = 3000.milliseconds proc resetMessageQueues(nodes: varargs[EthereumNode]) = for node in nodes: @@ -23,7 +23,8 @@ proc resetMessageQueues(nodes: varargs[EthereumNode]) = # check on a condition until true or return a future containing false # if timeout expires first -proc eventually(timeout: int, condition: proc(): bool {.gcsafe.}): Future[bool] = +proc eventually(timeout: Duration, condition: proc(): bool {.gcsafe.}): + Future[bool] = let wrappedCondition = proc(): Future[bool] {.async.} = let f = newFuture[bool]() while not condition(): @@ -76,7 +77,8 @@ suite "Waku connections": proc handler1(msg: ReceivedMessage) = var count {.global.}: int - check msg.decoded.payload == payloads[0] or msg.decoded.payload == payloads[1] + check msg.decoded.payload == payloads[0] or + msg.decoded.payload == payloads[1] count += 1 if count == 2: futures[0].complete(1) proc handler2(msg: ReceivedMessage) = @@ -84,7 +86,8 @@ suite "Waku connections": futures[1].complete(1) proc handler3(msg: ReceivedMessage) = var count {.global.}: int - check msg.decoded.payload == payloads[2] or msg.decoded.payload == payloads[3] + check msg.decoded.payload == payloads[2] or + msg.decoded.payload == payloads[3] count += 1 if count == 2: futures[2].complete(1) proc handler4(msg: ReceivedMessage) = @@ -93,19 +96,17 @@ suite "Waku connections": # Filters # filter for encrypted asym - filters.add(node1.subscribeFilter(initFilter(privateKey = some(encryptKeyPair.seckey), - topics = @[topic]), handler1)) + filters.add(node1.subscribeFilter(initFilter( + privateKey = some(encryptKeyPair.seckey), topics = @[topic]), handler1)) # filter for encrypted asym + signed filters.add(node1.subscribeFilter(initFilter(some(signKeyPair.pubkey), - privateKey = some(encryptKeyPair.seckey), - topics = @[topic]), handler2)) + privateKey = some(encryptKeyPair.seckey), topics = @[topic]), handler2)) # filter for encrypted sym filters.add(node1.subscribeFilter(initFilter(symKey = some(symKey), - topics = @[topic]), handler3)) + topics = @[topic]), handler3)) # filter for encrypted sym + signed filters.add(node1.subscribeFilter(initFilter(some(signKeyPair.pubkey), - symKey = some(symKey), - topics = @[topic]), handler4)) + symKey = some(symKey), topics = @[topic]), handler4)) # Messages check: # encrypted asym @@ -182,10 +183,10 @@ suite "Waku connections": check msg.decoded.payload == payload futures[1].complete(1) - var filter1 = node1.subscribeFilter(initFilter(topics = @[topic], powReq = 0), - handler1) - var filter2 = node1.subscribeFilter(initFilter(topics = @[topic], - powReq = 1_000_000), handler2) + var filter1 = node1.subscribeFilter( + initFilter(topics = @[topic], powReq = 0), handler1) + var filter2 = node1.subscribeFilter( + initFilter(topics = @[topic], powReq = 1_000_000), handler2) check: node2.postMessage(ttl = safeTTL, topic = topic, payload = payload) == true @@ -246,7 +247,8 @@ suite "Waku connections": proc handler(msg: ReceivedMessage) = check msg.decoded.payload == payload f.complete(1) - var filter = node1.subscribeFilter(initFilter(topics = filterTopics), handler) + var filter = node1.subscribeFilter( + initFilter(topics = filterTopics), handler) await node1.setBloomFilter(node1.filtersToBloom()) check: @@ -314,7 +316,7 @@ suite "Waku connections": # to uint32 in postMessage() let lowerTTL = 2'u32 # Lower TTL as we need to wait for messages to expire for i in countdown(10, 1): - check node2.postMessage(ttl = lowerTTL, topic = topic, payload = payload) == true + check node2.postMessage(ttl = lowerTTL, topic = topic, payload = payload) check node2.protocolState(Waku).queue.items.len == 10 await sleepAsync(waitInterval) @@ -338,6 +340,10 @@ suite "Waku connections": var filter = node1.subscribeFilter(initFilter(topics = @[topic], allowP2P = true), handler) + # Need to be sure that node1 is added in the peerpool of node2 as + # postMessage with target will iterate over the peers + require await eventually(conditionTimeoutMs, + proc(): bool = node2.peerPool.len == 1) check: node1.setPeerTrusted(toNodeId(node2.keys.pubkey)) == true node2.postMessage(ttl = 10, topic = topic, @@ -472,9 +478,11 @@ suite "Waku connections": peer.state(Waku).bloom == bloom peer.state(Waku).topics == some(topics) - let hasBloomNodeConnectedCondition = proc(): bool = wakuBloomNode.peerPool.len == 1 + let hasBloomNodeConnectedCondition = proc(): bool = + wakuBloomNode.peerPool.len == 1 # wait for the peer to be connected on the other side - let hasBloomNodeConnected = await eventually(conditionTimeoutMs, hasBloomNodeConnectedCondition) + let hasBloomNodeConnected = + await eventually(conditionTimeoutMs, hasBloomNodeConnectedCondition) # check bloom filter is updated check: hasBloomNodeConnected @@ -487,9 +495,11 @@ suite "Waku connections": let bloomFilterUpdatedCondition = proc(): bool = for peer in wakuNode.peerPool.peers: - return peer.state(Waku).bloom == bloom and peer.state(Waku).topics == none(seq[Topic]) + return peer.state(Waku).bloom == bloom and + peer.state(Waku).topics == none(seq[Topic]) - let bloomFilterUpdated = await eventually(conditionTimeoutMs, bloomFilterUpdatedCondition) + let bloomFilterUpdated = + await eventually(conditionTimeoutMs, bloomFilterUpdatedCondition) # check bloom filter is updated check: bloomFilterUpdated @@ -516,9 +526,8 @@ suite "Waku connections": wakuNode.postMessage(ttl = safeTTL, topic = wrongTopic, payload = payload) wakuNode.protocolState(Waku).queue.items.len == 3 - let response = await eventually(conditionTimeoutMs, proc (): bool = wakuTopicNode.protocolState(Waku).queue.items.len == 2) - check: - response + await eventually(conditionTimeoutMs, + proc (): bool = wakuTopicNode.protocolState(Waku).queue.items.len == 2) asyncTest "Waku topic-interest versus bloom filter": var From d0d931db0a35b61373cdd77b56574f28a7924bee Mon Sep 17 00:00:00 2001 From: kdeme Date: Mon, 4 May 2020 18:20:35 +0200 Subject: [PATCH 9/9] Correct wakunode dockerfile --- waku/node/v1/docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/waku/node/v1/docker/Dockerfile b/waku/node/v1/docker/Dockerfile index b4f1589db..8d061e6e0 100644 --- a/waku/node/v1/docker/Dockerfile +++ b/waku/node/v1/docker/Dockerfile @@ -9,8 +9,8 @@ RUN apt-get -qq update \ ARG GIT_REVISION RUN cd /root \ - && git clone https://github.com/status-im/nimbus.git \ - && cd nimbus \ + && git clone https://github.com/status-im/nim-waku.git \ + && cd nim-waku \ && git reset --hard ${GIT_REVISION} \ && { make &>/dev/null || true; } \ && make -j$(nproc) update \ @@ -28,7 +28,7 @@ RUN apt-get -qq update \ && apt-get -qq clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -COPY --from=build /root/nimbus/build/wakunode /usr/bin/wakunode +COPY --from=build /root/nim-waku/build/wakunode /usr/bin/wakunode MAINTAINER Kim De Mey LABEL description="Wakunode: Waku and Whisper client"