mirror of
https://github.com/logos-messaging/logos-messaging-go.git
synced 2026-01-12 02:43:08 +00:00
Compare commits
No commits in common. "master" and "v0.6.0" have entirely different histories.
@ -1,16 +0,0 @@
|
||||
plugins:
|
||||
# golint:
|
||||
# enabled: true
|
||||
gofmt:
|
||||
enabled: true
|
||||
govet:
|
||||
enabled: true
|
||||
# golangci-lint:
|
||||
# enabled: true
|
||||
exclude_patterns:
|
||||
- "."
|
||||
- "**/*.pb.go"
|
||||
- "**/rln/contracts/*.go"
|
||||
- "**/bindata.go"
|
||||
- "./examples/waku-csharp"
|
||||
- "./examples/swift-waku"
|
||||
@ -2,5 +2,6 @@ README.md
|
||||
Dockerfile
|
||||
.*ignore
|
||||
LICENSE*
|
||||
tests
|
||||
examples
|
||||
*.db
|
||||
|
||||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -1 +0,0 @@
|
||||
* @richard-ramos @chaitanyaprem
|
||||
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,36 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: 'bug:'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
### go-waku version/commit hash
|
||||
State the version of `go-waku` where you've encountered the bug or, if built off a specific commit, the relevant commit hash. You can check the version by running `./build/waku --version`.
|
||||
- e.g. `v0.7.0` or `e21bdab`
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
40
.github/ISSUE_TEMPLATE/epic.md
vendored
40
.github/ISSUE_TEMPLATE/epic.md
vendored
@ -1,40 +0,0 @@
|
||||
---
|
||||
name: Epic
|
||||
about: Track Epic
|
||||
title: "[Epic] "
|
||||
labels: epic
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Please ensure you are assigning the matching milestone label to the epic -->
|
||||
<!-- All _active_ (being worked on) epics MUST have an owner (GitHub assignee) -->
|
||||
|
||||
**Planned start date**:
|
||||
**Due date**:
|
||||
|
||||
# Summary
|
||||
|
||||
<!-- Provide a high level summary of the Epic -->
|
||||
|
||||
# Acceptance Criteria
|
||||
|
||||
<!-- describe the deliverable of this epic and its attributes in plain English -->
|
||||
|
||||
## Tasks
|
||||
|
||||
<!--
|
||||
Breakdown of the work
|
||||
- [ ] Task 1
|
||||
- [ ] Link to GitHub issue tracking task 2
|
||||
-->
|
||||
|
||||
# RAID (Risks, Assumptions, Issues and Dependencies)
|
||||
|
||||
<!-- List dependencies on other epics (avoid dependencies on tasks) -->
|
||||
|
||||
<!-- List dependencies on other teams -->
|
||||
|
||||
<!-- List any risks or assumptions that will be cleared as work progresses -->
|
||||
|
||||
<!-- List any GitHub issues that tracks any blocker or any of the items above -->
|
||||
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,23 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for go-waku implementation
|
||||
title: 'feat:'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Problem
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
### Suggested solution
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
### Alternatives considered
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
### Additional context
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
### Acceptance criteria
|
||||
A list of tasks that need to be done for the issue to be considered resolved.
|
||||
18
.github/ISSUE_TEMPLATE/improvement.md
vendored
18
.github/ISSUE_TEMPLATE/improvement.md
vendored
@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Improvement
|
||||
about: Suggest improvements to the codebase or processes. This includes refactoring,
|
||||
docs and any other chores
|
||||
title: 'chore:'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Background
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]; There is a spelling error in [...]; It's difficult to read the code in module [...]
|
||||
|
||||
### Details
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
### Acceptance criteria
|
||||
A list of tasks that need to be done for the issue to be considered resolved.
|
||||
6
.github/docker-compose/ganache.yml
vendored
6
.github/docker-compose/ganache.yml
vendored
@ -1,6 +0,0 @@
|
||||
services:
|
||||
ganache:
|
||||
image: "trufflesuite/ganache:latest"
|
||||
command: ["-m='swim relax risk shy chimney please usual search industry board music segment'"]
|
||||
ports:
|
||||
- "8545:8545"
|
||||
13
.github/docker-compose/nwaku.yml
vendored
13
.github/docker-compose/nwaku.yml
vendored
@ -1,13 +0,0 @@
|
||||
services:
|
||||
nwaku:
|
||||
image: "harbor.status.im/wakuorg/nwaku:v0.35.1"
|
||||
command:
|
||||
[
|
||||
"--relay",
|
||||
"--store",
|
||||
"--nodekey=1122334455667788990011223344556677889900112233445566778899001122",
|
||||
"--cluster-id=99",
|
||||
"--shard=1",
|
||||
]
|
||||
ports:
|
||||
- "60000"
|
||||
7
.github/docker-compose/postgres.yml
vendored
7
.github/docker-compose/postgres.yml
vendored
@ -1,7 +0,0 @@
|
||||
services:
|
||||
postgres:
|
||||
environment:
|
||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
image: "postgres:9.6-alpine"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
31
.github/pull_request_template.md
vendored
31
.github/pull_request_template.md
vendored
@ -1,31 +0,0 @@
|
||||
# Description
|
||||
<!--- Describe your changes to provide context for reviewrs -->
|
||||
|
||||
# Changes
|
||||
|
||||
<!-- List of detailed changes -->
|
||||
|
||||
- [ ] ...
|
||||
- [ ] ...
|
||||
|
||||
# Tests
|
||||
|
||||
<!-- List down any tests that were executed specifically for this pull-request -->
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
## How to test
|
||||
|
||||
1.
|
||||
1.
|
||||
1.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
## Issue
|
||||
|
||||
closes #
|
||||
-->
|
||||
4
.github/workflows/add-action-project.yml
vendored
4
.github/workflows/add-action-project.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
name: Add issue to project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.5.0
|
||||
- uses: actions/add-to-project@v0.3.0
|
||||
with:
|
||||
project-url: https://github.com/orgs/waku-org/projects/2
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_20240815 }}
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
|
||||
12
.github/workflows/auto_assign_pr.yml
vendored
12
.github/workflows/auto_assign_pr.yml
vendored
@ -1,12 +0,0 @@
|
||||
name: Auto Assign PR to Creator
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
assign_creator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: toshimaru/auto-author-assign@v1.6.2
|
||||
78
.github/workflows/build_linux_pkgs.yml
vendored
78
.github/workflows/build_linux_pkgs.yml
vendored
@ -1,78 +0,0 @@
|
||||
name: build_linux_pkgs
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # "e.g. v0.4"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: xom9ikk/dotenv@v2
|
||||
with:
|
||||
path: ".github/"
|
||||
- run: |
|
||||
echo "go_version=${{ env.GO_VERSION }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- run: |
|
||||
VERSION=$(cat ./VERSION)
|
||||
echo "waku_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
build-linux:
|
||||
needs: env
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
ext: [deb, rpm]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get submodules hash
|
||||
id: submodules
|
||||
run: |
|
||||
echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
vendor/
|
||||
.git/modules
|
||||
key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }}
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ needs.env.outputs.go_version }}
|
||||
cache: false
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
run: |
|
||||
make build
|
||||
mkdir ./build/linux
|
||||
cp ./build/waku ./build/linux/.
|
||||
strip --strip-unneeded ./build/linux/waku
|
||||
|
||||
- name: Package ${{ matrix.ext }}
|
||||
uses: bpicode/github-action-fpm@master
|
||||
with:
|
||||
fpm_args: ./build/linux/waku=/usr/bin/waku
|
||||
fpm_opts: '-p gowaku-${{ needs.env.outputs.waku_version }}-x86_64.${{ matrix.ext }} -n go-waku -t ${{ matrix.ext }} -s dir --license "MIT, Apache 2.0" --version ${{ needs.env.outputs.waku_version }} --architecture x86_64 --depends libc6 --description "Go implementation of Waku v2 protocols" --url "https://github.com/waku-org/go-waku" --maintainer "Richard Ramos <richard@status.im>"'
|
||||
|
||||
- name: Upload ${{ matrix.ext }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: gowaku-${{ needs.env.outputs.waku_version }}-x86_64.${{ matrix.ext }}
|
||||
path: ./gowaku-${{ needs.env.outputs.waku_version }}-x86_64.${{ matrix.ext }}
|
||||
if-no-files-found: error
|
||||
110
.github/workflows/build_mobile.yml
vendored
110
.github/workflows/build_mobile.yml
vendored
@ -1,110 +0,0 @@
|
||||
name: build_mobile
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # "e.g. v0.4"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: xom9ikk/dotenv@v2
|
||||
with:
|
||||
path: ".github/"
|
||||
- run: |
|
||||
echo "go_version=${{ env.GO_VERSION }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- run: |
|
||||
VERSION=$(cat ./VERSION)
|
||||
echo "waku_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
build-android:
|
||||
needs: env
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get submodules hash
|
||||
id: submodules
|
||||
run: |
|
||||
echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
vendor/
|
||||
.git/modules
|
||||
key: ${{ runner.os }}-vendor-modules-${{ needs.env.outputs.go_version }}
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ needs.env.outputs.go_version }}
|
||||
cache: false
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make install-gomobile
|
||||
make mobile-android || make mobile-android
|
||||
cd ./build/lib
|
||||
tar -czvf gowaku-${{ needs.env.outputs.waku_version }}-android.tar.gz gowaku.aar gowaku-sources.jar
|
||||
|
||||
- name: Upload asset
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: gowaku-${{ needs.env.outputs.waku_version }}-android.tar.gz
|
||||
path: ./build/lib/gowaku-${{ needs.env.outputs.waku_version }}-android.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
build-ios:
|
||||
needs: env
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get submodules hash
|
||||
id: submodules
|
||||
run: |
|
||||
echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
vendor/
|
||||
.git/modules
|
||||
key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }}
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ needs.env.outputs.go_version }}
|
||||
cache: false
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make install-gomobile
|
||||
make mobile-ios
|
||||
cd ./build/lib
|
||||
tar -czvf gowaku-${{ needs.env.outputs.waku_version }}-ios.tar.gz Gowaku.xcframework
|
||||
|
||||
- name: Upload asset
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: gowaku-${{ needs.env.outputs.waku_version }}-ios.tar.gz
|
||||
path: ./build/lib/gowaku-${{ needs.env.outputs.waku_version }}-ios.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
169
.github/workflows/ci.yml
vendored
169
.github/workflows/ci.yml
vendored
@ -1,169 +0,0 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
changes: # changes detection
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
name: Checkout code
|
||||
id: checkout
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
common:
|
||||
- '.github/workflows/**'
|
||||
- 'Makefile'
|
||||
- 'libs/**'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'flake.nix'
|
||||
- 'examples/**'
|
||||
|
||||
v2:
|
||||
- 'waku/**'
|
||||
- 'cmd/**'
|
||||
- 'library/**'
|
||||
- 'tests/**'
|
||||
|
||||
docker:
|
||||
- 'docker/**'
|
||||
- 'Dockerfile'
|
||||
|
||||
outputs:
|
||||
common: ${{ steps.filter.outputs.common }}
|
||||
v2: ${{ steps.filter.outputs.v2 }}
|
||||
docker: ${{ steps.filter.outputs.docker }}
|
||||
|
||||
env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: |
|
||||
VERSION=$(cat ./VERSION)
|
||||
echo "waku_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
golangci:
|
||||
name: lint
|
||||
needs: [changes, env]
|
||||
if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: false
|
||||
|
||||
- name: Execute golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.64.6
|
||||
args: --timeout=5m
|
||||
|
||||
build:
|
||||
needs: [changes, env]
|
||||
if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
|
||||
name: build-${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get submodules hash
|
||||
id: submodules
|
||||
run: |
|
||||
echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
vendor/
|
||||
.git/modules
|
||||
key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }}
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: false
|
||||
|
||||
- name: Build binary
|
||||
run: make
|
||||
|
||||
- name: Build library
|
||||
run: make static-library dynamic-library
|
||||
|
||||
- name: Build examples
|
||||
run: make build-example
|
||||
|
||||
test:
|
||||
needs: [changes, env]
|
||||
if: ${{ needs.changes.outputs.v2 == 'true' || needs.changes.outputs.common == 'true' }}
|
||||
strategy:
|
||||
matrix:
|
||||
tests: [test-ci, test-with-race]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
name: ${{ matrix.tests }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get submodules hash
|
||||
id: submodules
|
||||
run: |
|
||||
echo "hash=$(git submodule status | awk '{print $1}' | sort | shasum -a 256 | sed 's/[ -]*//g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
vendor/
|
||||
.git/modules
|
||||
key: ${{ runner.os }}-vendor-modules-${{ steps.submodules.outputs.hash }}
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: false
|
||||
|
||||
- name: "Run tests"
|
||||
run: make ${{ matrix.tests }}
|
||||
|
||||
- name: "Run onchain-tests"
|
||||
run: |
|
||||
docker compose -f .github/docker-compose/ganache.yml up -d
|
||||
make test-onchain${{ matrix.tests == 'test-with-race' && '-with-race' || '' }}
|
||||
|
||||
- name: "Run storev3 tests"
|
||||
run: |
|
||||
docker compose -f .github/docker-compose/nwaku.yml up -d
|
||||
NWAKU_HOST=$(docker compose -f .github/docker-compose/nwaku.yml port nwaku 60000)
|
||||
NWAKU_PORT=$(echo $NWAKU_HOST | cut -d ":" -f 2)
|
||||
sleep 5
|
||||
make test-storev3 TEST_STOREV3_NODE="/ip4/127.0.0.1/tcp/${NWAKU_PORT}/p2p/16Uiu2HAmMGhfSTUzKbsjMWxc6T1X4wiTWSF1bEWSLjAukCm7KiHV"
|
||||
50
.github/workflows/container-image.yml
vendored
50
.github/workflows/container-image.yml
vendored
@ -1,50 +0,0 @@
|
||||
name: container-image-build
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_tag:
|
||||
type: string
|
||||
default: ${{ github.event.number }}
|
||||
outputs:
|
||||
image:
|
||||
description: The resulting image link
|
||||
value: ${{ jobs.build-docker-image.outputs.image }}
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-docker-image:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
|
||||
name: docker-build-${{ matrix.os }}
|
||||
outputs:
|
||||
image: ${{ steps.build.outputs.image }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build image
|
||||
id: build
|
||||
run: |
|
||||
|
||||
SHORT_REF=$(git rev-parse --short HEAD)
|
||||
|
||||
TAG=$([ "${PR_NUMBER}" == "" ] && echo "${SHORT_REF}" || echo "${PR_NUMBER}")
|
||||
IMAGE=quay.io/wakuorg/go-waku-pr:${TAG}
|
||||
|
||||
echo "image=${IMAGE}" >> $GITHUB_OUTPUT
|
||||
echo "commit_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
docker login -u ${QUAY_USER} -p ${QUAY_PASSWORD} quay.io
|
||||
docker build -t ${IMAGE} -f docker/Dockerfile.test.amd64 --label quay.expires-after=7d .
|
||||
docker push ${IMAGE}
|
||||
env:
|
||||
QUAY_PASSWORD: ${{ secrets.QUAY_PASSWORD }}
|
||||
QUAY_USER: ${{ secrets.QUAY_USER }}
|
||||
PR_NUMBER: ${{ inputs.image_tag }}
|
||||
|
||||
43
.github/workflows/lint_pr.yml
vendored
43
.github/workflows/lint_pr.yml
vendored
@ -1,43 +0,0 @@
|
||||
name: "Conventional Commits"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
main:
|
||||
name: Validate format
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
id: lint_pr_title
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: richard-ramos/action-conventional-commits@v1.1.1
|
||||
id: lint_pr_commits
|
||||
- uses: marocchino/sticky-pull-request-comment@v2
|
||||
# When the previous steps fails, the workflow would stop. By adding this
|
||||
# condition you can continue the execution with the populated error message.
|
||||
if: always() && (steps.lint_pr_title.outputs.error_message != null || steps.lint_pr_commits.outputs.error_message != null )
|
||||
with:
|
||||
header: pr-title-lint-error
|
||||
message: |
|
||||
Thank you for opening this pull request!
|
||||
|
||||
We require pull request titles and commits to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your PR needs to be adjusted.
|
||||
|
||||
Details:
|
||||
|
||||
> ${{ steps.lint_pr_title.outputs.error_message }}
|
||||
> ${{ steps.lint_pr_commits.outputs.error_message }}
|
||||
|
||||
# Delete a previous comment when the issue has been resolved
|
||||
- if: ${{ steps.lint_pr_title.outputs.error_message == null && steps.lint_pr_commits.outputs.error_message == null }}
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
header: pr-title-lint-error
|
||||
delete: true
|
||||
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,10 +1,9 @@
|
||||
.codeclimate.yml
|
||||
nodekey
|
||||
rlnKeystore.json
|
||||
rlnCredentials.txt
|
||||
rlnCredentials.json
|
||||
test_onchain.json
|
||||
*.bkp
|
||||
*.log
|
||||
.vscode
|
||||
|
||||
# sqlite db
|
||||
*.db
|
||||
@ -27,18 +26,18 @@ pkg/*
|
||||
|
||||
# output binaries
|
||||
go-waku
|
||||
examples/basic-relay/build/basic-relay
|
||||
examples/filter2/build/filter2
|
||||
examples/noise/build/
|
||||
examples/noise/noise
|
||||
examples/basic-light-client/basic2
|
||||
examples/basic-relay/basic2
|
||||
examples/filter2/filter2
|
||||
examples/rln/rln
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
*.out.tmp
|
||||
coverage.html
|
||||
coverage.json
|
||||
|
||||
cc-test-reporter
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
@ -62,12 +61,6 @@ Icon
|
||||
# Nix
|
||||
result
|
||||
|
||||
# Solidity files
|
||||
waku/v2/protocol/rln/contracts/*.abi
|
||||
waku/v2/protocol/rln/contracts/*.sol
|
||||
waku/v2/protocol/rln/contracts/*.bin
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
@ -183,5 +176,3 @@ iOSInjectionProject/
|
||||
**/xcshareddata/WorkspaceSettings.xcsettings
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/swift,xcode,Cobjective-c,osx
|
||||
|
||||
.idea
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,6 +0,0 @@
|
||||
[submodule "libs/waku-rln-contract"]
|
||||
path = libs/waku-rln-contract
|
||||
url = https://github.com/waku-org/waku-rln-contract.git
|
||||
[submodule "waku/v2/protocol/waku-proto"]
|
||||
path = waku/v2/protocol/waku-proto
|
||||
url = https://github.com/waku-org/waku-proto
|
||||
@ -1,8 +0,0 @@
|
||||
issues:
|
||||
include:
|
||||
- EXC0012
|
||||
- EXC0014
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- revive
|
||||
3
.golangci.yaml
Normal file
3
.golangci.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
run:
|
||||
build-tags:
|
||||
- gowaku_rln
|
||||
11
Dockerfile
11
Dockerfile
@ -1,5 +1,10 @@
|
||||
# BUILD IMAGE --------------------------------------------------------
|
||||
FROM golang:1.23 as builder
|
||||
FROM golang:1.19-alpine3.16 as builder
|
||||
|
||||
# Get build tools and required header files
|
||||
RUN apk add --no-cache build-base
|
||||
RUN apk add --no-cache bash
|
||||
RUN apk add --no-cache git
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
@ -9,7 +14,7 @@ RUN make -j$(nproc) build
|
||||
|
||||
# ACTUAL IMAGE -------------------------------------------------------
|
||||
|
||||
FROM debian:12.1-slim
|
||||
FROM alpine:3.16
|
||||
|
||||
ARG GIT_COMMIT=unknown
|
||||
|
||||
@ -21,8 +26,6 @@ LABEL commit=$GIT_COMMIT
|
||||
# color, nocolor, json
|
||||
ENV GOLOG_LOG_FMT=nocolor
|
||||
|
||||
RUN apt update && apt install -y ca-certificates
|
||||
|
||||
# go-waku default ports
|
||||
EXPOSE 9000 30303 60000 60001 8008 8009
|
||||
|
||||
|
||||
144
Makefile
144
Makefile
@ -1,11 +1,14 @@
|
||||
|
||||
CC_TEST_REPORTER_ID := c09efa7c67c269bfdc6f8a356785d8f7ed55c9dc2b9a1d07b78c384f55c4e527
|
||||
GO_HTML_COV := ./coverage.html
|
||||
GO_TEST_OUTFILE := ./c.out
|
||||
CC_PREFIX := github.com/waku-org/go-waku
|
||||
|
||||
SHELL := bash # the shell used internally by Make
|
||||
|
||||
GOCMD ?= $(shell which go)
|
||||
GOBIN ?= $(shell which go)
|
||||
|
||||
.PHONY: all build lint lint-full test build-example static-library dynamic-library test-c test-c-template mobile-android mobile-ios
|
||||
.PHONY: all build lint test coverage build-example static-library dynamic-library test-c test-c-template mobile-android mobile-ios
|
||||
|
||||
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
|
||||
detected_OS := Windows
|
||||
@ -15,13 +18,11 @@ endif
|
||||
|
||||
ifeq ($(detected_OS),Darwin)
|
||||
GOBIN_SHARED_LIB_EXT := dylib
|
||||
TEST_REPORTER_URL := https://codeclimate.com/downloads/test-reporter/test-reporter-latest-darwin-amd64
|
||||
else ifeq ($(detected_OS),Windows)
|
||||
# on Windows need `--export-all-symbols` flag else expected symbols will not be found in libgowaku.dll
|
||||
GOBIN_SHARED_LIB_CGO_LDFLAGS := CGO_LDFLAGS="-Wl,--export-all-symbols"
|
||||
GOBIN_SHARED_LIB_EXT := dll
|
||||
else
|
||||
TEST_REPORTER_URL := https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
|
||||
GOBIN_SHARED_LIB_EXT := so
|
||||
GOBIN_SHARED_LIB_CGO_LDFLAGS := CGO_LDFLAGS="-Wl,-soname,libgowaku.so.0"
|
||||
endif
|
||||
@ -39,70 +40,68 @@ BUILD_FLAGS ?= $(shell echo "-ldflags='\
|
||||
ANDROID_TARGET ?= 23
|
||||
|
||||
# control rln code compilation
|
||||
ifeq ($(NO_RLN), true)
|
||||
BUILD_TAGS := gowaku_no_rln
|
||||
ifeq ($(RLN), true)
|
||||
BUILD_TAGS := gowaku_rln
|
||||
endif
|
||||
|
||||
all: build
|
||||
|
||||
deps: lint-install
|
||||
|
||||
build-with-race:
|
||||
${GOCMD} build -race -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o build/waku ./cmd/waku
|
||||
|
||||
build:
|
||||
${GOCMD} build -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o build/waku ./cmd/waku
|
||||
${GOBIN} build -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o build/waku ./cmd/waku
|
||||
|
||||
chat2:
|
||||
pushd ./examples/chat2 && \
|
||||
${GOCMD} build -o ../../build/chat2 . && \
|
||||
${GOBIN} build -tags="gowaku_rln" -o ../../build/chat2 . && \
|
||||
popd
|
||||
|
||||
vendor:
|
||||
${GOCMD} mod tidy
|
||||
cd examples/basic-light-client && ${GOCMD} mod tidy
|
||||
cd examples/basic-relay && ${GOCMD} mod tidy
|
||||
cd examples/chat2-reliable && ${GOCMD} mod tidy
|
||||
cd examples/chat2 && ${GOCMD} mod tidy
|
||||
cd examples/filter2 && ${GOCMD} mod tidy
|
||||
cd examples/noise && ${GOCMD} mod tidy
|
||||
cd examples/rln && ${GOCMD} mod tidy
|
||||
${GOBIN} mod tidy
|
||||
|
||||
lint-install:
|
||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \
|
||||
bash -s -- -b $(shell ${GOCMD} env GOPATH)/bin v1.59.1
|
||||
bash -s -- -b $(shell ${GOBIN} env GOPATH)/bin v1.52.2
|
||||
|
||||
lint:
|
||||
@echo "lint"
|
||||
@golangci-lint run ./...
|
||||
|
||||
lint-full:
|
||||
@echo "lint"
|
||||
@golangci-lint run ./... --config=./.golangci.full.yaml
|
||||
|
||||
test-with-race:
|
||||
${GOCMD} test -race -timeout 300s ./waku/... ./cmd/waku/server/...
|
||||
@golangci-lint --exclude=SA1019 run ./... --deadline=5m
|
||||
|
||||
test:
|
||||
${GOCMD} test -timeout 300s ./waku/... ./cmd/waku/server/... ./...
|
||||
${GOBIN} test -timeout 300s ./waku/... -coverprofile=${GO_TEST_OUTFILE}.tmp
|
||||
cat ${GO_TEST_OUTFILE}.tmp | grep -v ".pb.go" > ${GO_TEST_OUTFILE}
|
||||
${GOBIN} tool cover -html=${GO_TEST_OUTFILE} -o ${GO_HTML_COV}
|
||||
|
||||
test-ci: test
|
||||
COVERAGE_FILE := ./coverage/cc-test-reporter
|
||||
$(COVERAGE_FILE):
|
||||
curl -sfL https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 --output ./coverage/cc-test-reporter # TODO: support mac and windows
|
||||
chmod +x ./coverage/cc-test-reporter
|
||||
|
||||
_before-cc: $(COVERAGE_FILE)
|
||||
|
||||
CC_TEST_REPORTER_ID=${CC_TEST_REPORTER_ID} ./coverage/cc-test-reporter before-build
|
||||
|
||||
_after-cc:
|
||||
GIT_COMMIT=$(git log | grep -m1 -oE '[^ ]+$') CC_TEST_REPORTER_ID=${CC_TEST_REPORTER_ID} ./coverage/cc-test-reporter after-build --prefix ${CC_PREFIX}
|
||||
|
||||
test-ci: _before-cc test _after-cc
|
||||
|
||||
generate:
|
||||
${GOCMD} generate ./...
|
||||
${GOBIN} generate ./...
|
||||
|
||||
coverage:
|
||||
${GOBIN} test -count 1 -coverprofile=coverage.out ./...
|
||||
${GOBIN} tool cover -html=coverage.out -o=coverage.html
|
||||
|
||||
# build a docker image for the fleet
|
||||
docker-image: DOCKER_IMAGE_TAG ?= latest
|
||||
docker-image: DOCKER_IMAGE_NAME ?= wakuorg/go-waku:$(DOCKER_IMAGE_TAG)
|
||||
docker-image: DOCKER_IMAGE_NAME ?= statusteam/go-waku:$(DOCKER_IMAGE_TAG)
|
||||
docker-image:
|
||||
docker build --tag $(DOCKER_IMAGE_NAME) \
|
||||
--build-arg="GIT_COMMIT=$(shell git rev-parse HEAD)" .
|
||||
|
||||
build-example-basic-relay:
|
||||
cd examples/basic-relay && $(MAKE)
|
||||
|
||||
build-example-basic-light-client:
|
||||
cd examples/basic-light-client && $(MAKE)
|
||||
build-example-basic2:
|
||||
cd examples/basic2 && $(MAKE)
|
||||
|
||||
build-example-chat-2:
|
||||
cd examples/chat2 && $(MAKE)
|
||||
@ -113,44 +112,28 @@ build-example-filter2:
|
||||
build-example-c-bindings:
|
||||
cd examples/c-bindings && $(MAKE)
|
||||
|
||||
build-example-noise:
|
||||
cd examples/noise && $(MAKE)
|
||||
|
||||
build-example-rln:
|
||||
cd examples/rln && $(MAKE)
|
||||
|
||||
build-example: build-example-basic-relay build-example-basic-light-client build-example-chat-2 build-example-filter2 build-example-c-bindings build-example-noise build-example-rln
|
||||
build-example: build-example-basic2 build-example-chat-2 build-example-filter2 build-example-c-bindings
|
||||
|
||||
static-library:
|
||||
@echo "Building static library..."
|
||||
${GOCMD} build \
|
||||
${GOBIN} build \
|
||||
-buildmode=c-archive \
|
||||
-tags="${BUILD_TAGS} gowaku_no_rln" \
|
||||
-tags="${BUILD_TAGS}" \
|
||||
-o ./build/lib/libgowaku.a \
|
||||
./library/c/
|
||||
./library/
|
||||
@echo "Static library built:"
|
||||
ifeq ($(detected_OS),Darwin)
|
||||
sed -i '' -e "s/#include <cgo_utils.h>//gi" ./build/lib/libgowaku.h
|
||||
else
|
||||
sed -i "s/#include <cgo_utils.h>//gi" ./build/lib/libgowaku.h
|
||||
endif
|
||||
@ls -la ./build/lib/libgowaku.*
|
||||
|
||||
dynamic-library:
|
||||
@echo "Building shared library..."
|
||||
rm -f ./build/lib/libgowaku.$(GOBIN_SHARED_LIB_EXT)*
|
||||
$(GOBIN_SHARED_LIB_CFLAGS) $(GOBIN_SHARED_LIB_CGO_LDFLAGS) ${GOCMD} build \
|
||||
$(GOBIN_SHARED_LIB_CFLAGS) $(GOBIN_SHARED_LIB_CGO_LDFLAGS) ${GOBIN} build \
|
||||
-buildmode=c-shared \
|
||||
-tags="${BUILD_TAGS} gowaku_no_rln" \
|
||||
-tags="${BUILD_TAGS}" \
|
||||
-o ./build/lib/libgowaku.$(GOBIN_SHARED_LIB_EXT) \
|
||||
./library/c/
|
||||
ifeq ($(detected_OS),Darwin)
|
||||
sed -i '' -e "s/#include <cgo_utils.h>//gi" ./build/lib/libgowaku.h
|
||||
else
|
||||
sed -i "s/#include <cgo_utils.h>//gi" ./build/lib/libgowaku.h
|
||||
endif
|
||||
./library/
|
||||
ifeq ($(detected_OS),Linux)
|
||||
cd ./build/lib && \
|
||||
ls -lah . && \
|
||||
mv ./libgowaku.$(GOBIN_SHARED_LIB_EXT) ./libgowaku.$(GOBIN_SHARED_LIB_EXT).0 && \
|
||||
ln -s ./libgowaku.$(GOBIN_SHARED_LIB_EXT).0 ./libgowaku.$(GOBIN_SHARED_LIB_EXT)
|
||||
endif
|
||||
@ -160,30 +143,30 @@ endif
|
||||
mobile-android:
|
||||
@echo "Android target: ${ANDROID_TARGET} (override with ANDROID_TARGET var)"
|
||||
gomobile init && \
|
||||
${GOCMD} get -d golang.org/x/mobile/cmd/gomobile && \
|
||||
CGO=1 gomobile bind -v -target=android -androidapi=${ANDROID_TARGET} -ldflags="-s -w" -tags="${BUILD_TAGS} gowaku_no_rln" $(BUILD_FLAGS) -o ./build/lib/gowaku.aar ./library/mobile
|
||||
${GOBIN} get -d golang.org/x/mobile/cmd/gomobile && \
|
||||
gomobile bind -v -target=android -androidapi=${ANDROID_TARGET} -ldflags="-s -w" -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o ./build/lib/gowaku.aar ./mobile
|
||||
@echo "Android library built:"
|
||||
@ls -la ./build/lib/*.aar ./build/lib/*.jar
|
||||
|
||||
mobile-ios:
|
||||
gomobile init && \
|
||||
${GOCMD} get -d golang.org/x/mobile/cmd/gomobile && \
|
||||
gomobile bind -target=ios -ldflags="-s -w" -tags="nowatchdog ${BUILD_TAGS} gowaku_no_rln" $(BUILD_FLAGS) -o ./build/lib/Gowaku.xcframework ./library/mobile
|
||||
${GOBIN} get -d golang.org/x/mobile/cmd/gomobile && \
|
||||
gomobile bind -target=ios -ldflags="-s -w" -tags="nowatchdog ${BUILD_TAGS}" $(BUILD_FLAGS) -o ./build/lib/Gowaku.xcframework ./mobile
|
||||
@echo "IOS library built:"
|
||||
@ls -la ./build/lib/*.xcframework
|
||||
|
||||
install-xtools:
|
||||
${GOCMD} install golang.org/x/tools/...@v0.1.10
|
||||
${GOBIN} install golang.org/x/tools/...@v0.1.10
|
||||
|
||||
install-bindata:
|
||||
${GOCMD} install github.com/kevinburke/go-bindata/go-bindata@v3.13.0
|
||||
${GOBIN} install github.com/kevinburke/go-bindata/go-bindata@v3.13.0
|
||||
|
||||
install-gomobile: install-xtools
|
||||
${GOCMD} install golang.org/x/mobile/cmd/gomobile@v0.0.0-20220518205345-8578da9835fd
|
||||
${GOCMD} install golang.org/x/mobile/cmd/gobind@v0.0.0-20220518205345-8578da9835fd
|
||||
${GOBIN} install golang.org/x/mobile/cmd/gomobile@v0.0.0-20220518205345-8578da9835fd
|
||||
${GOBIN} install golang.org/x/mobile/cmd/gobind@v0.0.0-20220518205345-8578da9835fd
|
||||
|
||||
build-linux-pkg:
|
||||
docker build --build-arg UID=${UID} --build-arg GID=${GID} -f ./scripts/linux/Dockerfile -t wakuorg/gowaku-linux-pkgs:latest .
|
||||
docker build --build-arg UID=${UID} --build-arg GID=${GID} -f ./scripts/linux/Dockerfile -t statusteam/gowaku-linux-pkgs:latest .
|
||||
./scripts/linux/docker-run.sh
|
||||
ls -la ./build/*.rpm ./build/*.deb
|
||||
|
||||
@ -197,24 +180,5 @@ stop-ganache:
|
||||
|
||||
test-onchain: BUILD_TAGS += include_onchain_tests
|
||||
test-onchain:
|
||||
${GOCMD} test -v -count 1 -tags="${BUILD_TAGS}" github.com/waku-org/go-waku/waku/v2/protocol/rln
|
||||
${GOBIN} test -v -count 1 -tags="${BUILD_TAGS}" github.com/waku-org/go-waku/waku/v2/protocol/rln
|
||||
|
||||
test-onchain-with-race:
|
||||
${GOCMD} test -race -v -count 1 -tags="${BUILD_TAGS}" github.com/waku-org/go-waku/waku/v2/protocol/rln
|
||||
|
||||
test-postgres: PG_BUILD_TAGS = ${BUILD_TAGS} include_postgres_tests
|
||||
test-postgres:
|
||||
${GOCMD} test -p 1 -v -count 1 -tags="${PG_BUILD_TAGS}" github.com/waku-org/go-waku/waku/persistence/...
|
||||
|
||||
test-postgres-with-race:
|
||||
${GOCMD} test -race -p 1 -v -count 1 -tags="${PG_BUILD_TAGS}" github.com/waku-org/go-waku/waku/persistence/...
|
||||
|
||||
test-filter:
|
||||
${GOCMD} test -v github.com/waku-org/go-waku/waku/v2/protocol/filter -run TestFilterSuite -count=1
|
||||
|
||||
test-filter-api:
|
||||
${GOCMD} test -v github.com/waku-org/go-waku/waku/v2/api -run TestFilterApiSuite
|
||||
|
||||
TEST_STOREV3_NODE ?=
|
||||
test-storev3:
|
||||
TEST_STOREV3_NODE=${TEST_STOREV3_NODE} ${GOCMD} test -p 1 -v -count 1 -tags="${BUILD_TAGS} include_storev3_tests" github.com/waku-org/go-waku/waku/v2/protocol/store/...
|
||||
|
||||
18
README.md
18
README.md
@ -5,7 +5,8 @@ A Go implementation of the [Waku v2 protocol](https://rfc.vac.dev/spec/10).
|
||||
<p align="left">
|
||||
<a href="https://goreportcard.com/report/github.com/waku-org/go-waku"><img src="https://goreportcard.com/badge/github.com/waku-org/go-waku" /></a>
|
||||
<a href="https://godoc.org/github.com/waku-org/go-waku"><img src="http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square" /></a>
|
||||
<a href=""><img src="https://img.shields.io/badge/golang-%3E%3D1.20.0-orange.svg?style=flat-square" /></a>
|
||||
<a href=""><img src="https://img.shields.io/badge/golang-%3E%3D1.18.0-orange.svg?style=flat-square" /></a>
|
||||
<a href="https://lgtm.com/projects/g/waku-org/go-waku/alerts/"><img alt="Total alerts" src="https://img.shields.io/lgtm/alerts/g/waku-org/go-waku.svg?logo=lgtm&logoWidth=18"/></a>
|
||||
<a href="https://codeclimate.com/github/waku-org/go-waku/maintainability"><img src="https://api.codeclimate.com/v1/badges/426bdff6a339ff4d536b/maintainability" /></a>
|
||||
<br>
|
||||
</p>
|
||||
@ -38,19 +39,18 @@ nix develop
|
||||
#### Docker
|
||||
```
|
||||
docker run -i -t -p 60000:60000 -p 9000:9000/udp \
|
||||
wakuorg/go-waku:latest \
|
||||
--dns-discovery \
|
||||
--dns-discovery-url enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im \
|
||||
statusteam/go-waku:v0.5.2 \ # or, the image:tag of your choice
|
||||
--dns-discovery:true \
|
||||
--dns-discovery-url:enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@prod.waku.nodes.status.im \
|
||||
--discv5-discovery
|
||||
```
|
||||
or use the [image:tag](https://hub.docker.com/r/wakuorg/go-waku/tags) of your choice.
|
||||
|
||||
or build and run the image with:
|
||||
|
||||
```
|
||||
docker build -t wakuorg/go-waku:latest .
|
||||
docker build -t go-waku:latest .
|
||||
|
||||
docker run wakuorg/go-waku:latest --help
|
||||
docker run go-waku:latest --help
|
||||
```
|
||||
|
||||
#### Building on windows
|
||||
@ -85,7 +85,7 @@ make mobile-ios
|
||||
- [Send messages using Waku Lightpush](docs/api/lightpush.md)
|
||||
- [Encrypting and decrypting Waku Messages](docs/api/encoding.md)
|
||||
- [Retrieve message history using Waku Store](docs/api/store.md)
|
||||
- [C Bindings](library/c/README.md)
|
||||
- [C Bindings](library/README.md)
|
||||
- [Waku Specs](https://rfc.vac.dev/spec), has information of [waku topics](https://rfc.vac.dev/spec/23/), wakuv1/[wakuv2](https://rfc.vac.dev/spec/14/) message, [rln relay](https://rfc.vac.dev/spec/58/) etc.
|
||||
- [Enr](https://eips.ethereum.org/EIPS/eip-778), [Enrtree](https://eips.ethereum.org/EIPS/eip-1459)
|
||||
- [devp2p](https://github.com/ethereum/go-ethereum/tree/master/cmd/devp2p) tool for playing with enr/entree sync tree. [Tutorial](https://geth.ethereum.org/docs/developers/geth-developer/dns-discovery-setup)
|
||||
@ -107,7 +107,7 @@ Thank you for considering to help out with the source code! We welcome contribut
|
||||
If you'd like to contribute to go-waku, please fork, fix, commit and send a pull request. If you wish to submit more complex changes though, please check up with the core devs first to ensure those changes are in line with the general philosophy of the project and/or get some early feedback which can make both your efforts much lighter as well as our review and merge procedures quick and simple.
|
||||
|
||||
To build and test this repository, you need:
|
||||
- [Go](https://golang.org/) (version 1.20)
|
||||
- [Go](https://golang.org/) (version 1.17 or later)
|
||||
- [protoc](https://grpc.io/docs/protoc-installation/)
|
||||
- [protoc-gen-go](https://protobuf.dev/getting-started/gotutorial/#compiling-protocol-buffers)
|
||||
|
||||
|
||||
99
ci/Jenkinsfile
vendored
Normal file
99
ci/Jenkinsfile
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 40, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '30',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
}
|
||||
|
||||
/* WARNING: Defining parameters here with the ?: trick causes them to remember last value. */
|
||||
parameters {
|
||||
booleanParam(
|
||||
name: 'PUBLISH',
|
||||
description: 'Trigger publishing of build results for nightly or release.',
|
||||
defaultValue: getPublishDefault(params.PUBLISH),
|
||||
)
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Build') {
|
||||
parallel {
|
||||
stage('iOS') { steps { script {
|
||||
ios = jenkins.Build('go-waku/platforms/ios')
|
||||
} } }
|
||||
stage('Android') { steps { script {
|
||||
android = jenkins.Build('go-waku/platforms/android')
|
||||
} } }
|
||||
stage('Linux') { steps { script {
|
||||
linux = jenkins.Build('go-waku/platforms/linux')
|
||||
} } }
|
||||
}
|
||||
}
|
||||
stage('Archive') {
|
||||
steps { script {
|
||||
sh('rm -f pkg/*')
|
||||
jenkins.copyArts(ios)
|
||||
jenkins.copyArts(android)
|
||||
jenkins.copyArts(linux)
|
||||
sha = "pkg/${utils.pkgFilename(ext: 'sha256')}"
|
||||
dir('pkg') {
|
||||
/* generate sha256 checksums for upload */
|
||||
sh "sha256sum * | tee ../${sha}"
|
||||
archiveArtifacts('*')
|
||||
}
|
||||
} }
|
||||
}
|
||||
stage('Upload') {
|
||||
steps { script {
|
||||
/* object for easier URLs handling */
|
||||
urls = [
|
||||
/* mobile */
|
||||
Android: utils.pkgUrl(android),
|
||||
iOS: utils.pkgUrl(ios),
|
||||
Linux: utils.pkgUrl(linux),
|
||||
/* upload the sha256 checksums file too */
|
||||
SHA: s3.uploadArtifact(sha),
|
||||
]
|
||||
/* add URLs to the build description */
|
||||
jenkins.setBuildDesc(urls)
|
||||
} }
|
||||
}
|
||||
stage('Publish') {
|
||||
when { expression { params.PUBLISH } }
|
||||
steps { script {
|
||||
github.publishReleaseFiles(repo: 'status-desktop');
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper that generates list of available choices for a parameter
|
||||
* but re-orders them based on the currently set value. First is default. */
|
||||
def List genChoices(String previousChoice, List defaultChoices) {
|
||||
if (previousChoice == null) {
|
||||
return defaultChoices
|
||||
}
|
||||
choices = defaultChoices.minus(previousChoice)
|
||||
choices.add(0, previousChoice)
|
||||
return choices
|
||||
}
|
||||
|
||||
/* Helper that makes PUBLISH default to 'false' unless:
|
||||
* - The build is for a release branch
|
||||
* - A user explicitly specified a value
|
||||
* Since release builds create and re-create GitHub drafts every time. */
|
||||
def Boolean getPublishDefault(Boolean previousValue) {
|
||||
if (env.JOB_NAME.startsWith('go-waku/release')) { return true }
|
||||
if (previousValue != null) { return previousValue }
|
||||
return false
|
||||
}
|
||||
82
ci/Jenkinsfile.android
Normal file
82
ci/Jenkinsfile.android
Normal file
@ -0,0 +1,82 @@
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux && nix-2.11 && x86_64' }
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
/* Go requires a certain directory structure */
|
||||
checkoutToSubdirectory('src/github.com/waku-org/go-waku')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/go-waku/*')
|
||||
}
|
||||
|
||||
environment {
|
||||
CC = "gcc-10"
|
||||
/* Other stuff */
|
||||
TARGET = 'android'
|
||||
REPO = "${env.WORKSPACE}/src/github.com/waku-org/go-waku"
|
||||
GOCACHE = "${env.WORKSPACE_TMP}/go-build"
|
||||
GOPATH = "${env.WORKSPACE}"
|
||||
PATH = "${env.PATH}:${env.GOPATH}/bin"
|
||||
/* Android SDK */
|
||||
ANDROID_HOME = '/usr/lib/android-sdk'
|
||||
ANDROID_SDK_ROOT = '/usr/lib/android-sdk'
|
||||
/* gomobile requires a specific NDK version */
|
||||
ANDROID_NDK = "/opt/android-ndk-r23c"
|
||||
ANDROID_NDK_HOME = "/opt/android-ndk-r23c"
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage('Prep') { steps { script { dir(env.REPO) {
|
||||
env.ARTIFACT = "${env.REPO}/pkg/" + utils.pkgFilename(
|
||||
name: "go-waku",
|
||||
type: "android",
|
||||
ext: "tar.gz"
|
||||
)
|
||||
|
||||
nix.develop('make install-gomobile', pure: false)
|
||||
} } } }
|
||||
|
||||
stage('Build') { steps { script { dir(env.REPO) {
|
||||
/* First gomobile run always fails.
|
||||
* https://github.com/golang/go/issues/37372 */
|
||||
nix.develop('make mobile-android || make mobile-android', pure: false)
|
||||
dir('build/lib') {
|
||||
sh 'tar -czvf gowaku-android.tar.gz gowaku.aar gowaku-sources.jar'
|
||||
sh "cp gowaku-android.tar.gz ${env.ARTIFACT}"
|
||||
}
|
||||
} } } }
|
||||
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps { script {
|
||||
archiveArtifacts(env.ARTIFACT.minus("${env.WORKSPACE}/"))
|
||||
} }
|
||||
}
|
||||
stage('Upload') {
|
||||
steps { script {
|
||||
env.PKG_URL = s3.uploadArtifact(env.ARTIFACT)
|
||||
jenkins.setBuildDesc(android: env.PKG_URL)
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
@ -11,30 +11,18 @@ pipeline {
|
||||
)
|
||||
string(
|
||||
name: 'IMAGE_NAME',
|
||||
defaultValue: 'statusteam/go-waku',
|
||||
description: 'Docker image name.',
|
||||
defaultValue: params.IMAGE_NAME ?: 'waku-org/go-waku',
|
||||
)
|
||||
string(
|
||||
name: 'IMAGE_TAG',
|
||||
defaultValue: env.JOB_BASE_NAME == 'release' ? 'stable' : 'deploy-test',
|
||||
description: 'Docker image tag.',
|
||||
defaultValue: getDefaultImageTag(params.IMAGE_TAG)
|
||||
)
|
||||
string(
|
||||
name: 'DOCKER_CRED',
|
||||
description: 'Name of Docker Registry credential.',
|
||||
defaultValue: params.DOCKER_CRED ?: 'harbor-wakuorg-robot',
|
||||
)
|
||||
string(
|
||||
name: 'DOCKER_REGISTRY_URL',
|
||||
description: 'URL of the Docker Registry',
|
||||
defaultValue: params.DOCKER_REGISTRY_URL ?: 'https://harbor.status.im'
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableRestartFromStage()
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '30',
|
||||
@ -44,38 +32,83 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps { script {
|
||||
def imageTag = GIT_COMMIT.take(8)
|
||||
if (env.JOB_BASE_NAME == 'release') {
|
||||
imageTag = params.GIT_REF
|
||||
}
|
||||
image = docker.build(
|
||||
"${params.IMAGE_NAME}:${params.IMAGE_TAG ?: GIT_COMMIT.take(8)}",
|
||||
"${params.IMAGE_NAME}:${imageTag}",
|
||||
"--build-arg='GIT_COMMIT=${GIT_COMMIT.take(8)}' ."
|
||||
)
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Push') {
|
||||
when { expression { params.IMAGE_TAG != '' } }
|
||||
steps { script {
|
||||
withDockerRegistry([
|
||||
credentialsId: params.DOCKER_CRED, url: params.DOCKER_REGISTRY_URL
|
||||
credentialsId: "dockerhub-statusteam-auto", url: ""
|
||||
]) {
|
||||
image.push()
|
||||
/* If Git ref is a tag push it as Docker tag too. */
|
||||
if (params.GIT_REF ==~ /v\d+\.\d+\.\d+.*/) {
|
||||
image.push(params.GIT_REF)
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Deploy') {
|
||||
steps { script {
|
||||
withDockerRegistry([
|
||||
credentialsId: "dockerhub-statusteam-auto", url: ""
|
||||
]) {
|
||||
image.push(env.IMAGE_TAG)
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script {
|
||||
discordNotify(
|
||||
header: 'Go-Waku build successful!',
|
||||
cred: 'discord-waku-deployments-webhook',
|
||||
)
|
||||
} }
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
|
||||
def getDefaultImageTag(currentValue) {
|
||||
switch (env.JOB_BASE_NAME) {
|
||||
case 'docker-latest': return 'latest'
|
||||
case 'docker-release': return 'stable'
|
||||
case 'docker-manual': return ''
|
||||
default: return currentValue
|
||||
def discordNotify(Map args=[:]) {
|
||||
def opts = [
|
||||
header: args.header ?: 'Deployment successful!',
|
||||
cred: args.cred ?: null,
|
||||
]
|
||||
def repo = [
|
||||
url: GIT_URL.minus('.git'),
|
||||
branch: GIT_BRANCH.minus('origin/'),
|
||||
commit: GIT_COMMIT.take(8),
|
||||
prev: (
|
||||
env.GIT_PREVIOUS_SUCCESSFUL_COMMIT ?: env.GIT_PREVIOUS_COMMIT ?: 'master'
|
||||
).take(8),
|
||||
]
|
||||
wrap([$class: 'BuildUser']) {
|
||||
BUILD_USER_ID = env.BUILD_USER_ID
|
||||
}
|
||||
withCredentials([
|
||||
string(
|
||||
credentialsId: opts.cred,
|
||||
variable: 'DISCORD_WEBHOOK',
|
||||
),
|
||||
]) {
|
||||
discordSend(
|
||||
link: env.BUILD_URL,
|
||||
result: currentBuild.currentResult,
|
||||
webhookURL: env.DISCORD_WEBHOOK,
|
||||
title: "${env.JOB_NAME}#${env.BUILD_NUMBER}",
|
||||
description: """
|
||||
${opts.header}
|
||||
Image: [`${IMAGE_NAME}:${IMAGE_TAG}`](https://hub.docker.com/r/${IMAGE_NAME}/tags?name=${IMAGE_TAG})
|
||||
Branch: [`${repo.branch}`](${repo.url}/commits/${repo.branch})
|
||||
Commit: [`${repo.commit}`](${repo.url}/commit/${repo.commit})
|
||||
Diff: [`${repo.prev}...${repo.commit}`](${repo.url}/compare/${repo.prev}...${repo.commit})
|
||||
By: [`${BUILD_USER_ID}`](${repo.url}/commits?author=${BUILD_USER_ID})
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
78
ci/Jenkinsfile.ios
Normal file
78
ci/Jenkinsfile.ios
Normal file
@ -0,0 +1,78 @@
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos && nix-2.11 && aarch64' }
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
/* Go requires a certain directory structure */
|
||||
checkoutToSubdirectory('src/github.com/waku-org/go-waku')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/go-waku/*')
|
||||
}
|
||||
|
||||
environment {
|
||||
TARGET = 'ios'
|
||||
REPO = "${env.WORKSPACE}/src/github.com/waku-org/go-waku"
|
||||
GOCACHE = "${env.WORKSPACE_TMP}/go-build"
|
||||
GOPATH = "${env.WORKSPACE}"
|
||||
PATH = "${env.PATH}:${env.GOPATH}/bin"
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage('Prep') { steps { script { dir(env.REPO) {
|
||||
env.ARTIFACT = "${env.REPO}/pkg/" + utils.pkgFilename(
|
||||
name: "go-waku",
|
||||
type: "ios",
|
||||
ext: "tar.gz"
|
||||
)
|
||||
sh 'make install-gomobile'
|
||||
} } } }
|
||||
|
||||
stage('Build') {
|
||||
steps { script { dir(env.REPO) {
|
||||
nix.develop('which xcodebuild', pure: false)
|
||||
nix.develop('make mobile-ios', pure: false)
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Package') {
|
||||
steps { dir(env.REPO) {
|
||||
dir('build/lib') {
|
||||
sh 'tar -czvf gowaku-ios.tar.gz Gowaku.xcframework'
|
||||
sh "cp gowaku-ios.tar.gz ${env.ARTIFACT}"
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps { script {
|
||||
archiveArtifacts(env.ARTIFACT.minus("${env.WORKSPACE}/"))
|
||||
} }
|
||||
}
|
||||
stage('Upload') {
|
||||
steps { script {
|
||||
env.PKG_URL = s3.uploadArtifact(env.ARTIFACT)
|
||||
jenkins.setBuildDesc(ios: env.PKG_URL)
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
83
ci/Jenkinsfile.linux
Normal file
83
ci/Jenkinsfile.linux
Normal file
@ -0,0 +1,83 @@
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'linux && nix-2.11 && x86_64'
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
/* Go requires a certain directory structure */
|
||||
checkoutToSubdirectory('src/github.com/waku-org/go-waku')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/go-waku/*')
|
||||
}
|
||||
|
||||
environment {
|
||||
TARGET = 'linux'
|
||||
REPO = "${env.WORKSPACE}/src/github.com/waku-org/go-waku"
|
||||
GOCACHE = "${env.WORKSPACE_TMP}/go-build"
|
||||
GOPATH = "${env.WORKSPACE}"
|
||||
PATH = "${env.PATH}:${env.GOPATH}/bin"
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage('Prep') {
|
||||
steps { script { dir(env.REPO) {
|
||||
env.DEB_ARTIFACT = "${env.REPO}/pkg/" + utils.pkgFilename(
|
||||
name: "go-waku",
|
||||
type: "x86_64",
|
||||
ext: "deb"
|
||||
)
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps { script { dir(env.REPO) {
|
||||
nix.develop('make build')
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Package') {
|
||||
steps { script { dir(env.REPO) {
|
||||
dir('./scripts/linux') {
|
||||
nix.develop('./fpm-build.sh', attr: 'fpm')
|
||||
}
|
||||
dir('build') {
|
||||
sh "cp gowaku*.deb ${env.DEB_ARTIFACT}"
|
||||
}
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps { script {
|
||||
archiveArtifacts(env.DEB_ARTIFACT.minus("${env.WORKSPACE}/"))
|
||||
} }
|
||||
}
|
||||
stage('Upload') {
|
||||
steps { script {
|
||||
env.PKG_URL = s3.uploadArtifact(env.DEB_ARTIFACT)
|
||||
jenkins.setBuildDesc(x86_64_deb: env.PKG_URL)
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,12 @@
|
||||
library 'status-jenkins-lib@v1.9.26'
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'linux && nix-2.24 && x86_64'
|
||||
label 'linux && nix-2.11 && x86_64'
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableRestartFromStage()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
@ -28,7 +27,10 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps { script {
|
||||
nix.flake('node')
|
||||
sh("""#!/usr/bin/env bash
|
||||
${nix._sourceProfileInline()}
|
||||
nix build --print-out-paths .#node
|
||||
""")
|
||||
} }
|
||||
}
|
||||
stage('Check') {
|
||||
@ -43,12 +45,15 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps { script {
|
||||
nix.flake('static-library')
|
||||
sh("""#!/usr/bin/env bash
|
||||
${nix._sourceProfileInline()}
|
||||
nix build --print-out-paths .#library
|
||||
""")
|
||||
} }
|
||||
}
|
||||
stage('Check') {
|
||||
steps {
|
||||
sh 'readelf -h ./result/bin/libgowaku.a'
|
||||
sh 'ldd ./result/bin/library'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
ci/Jenkinsfile.tests
Normal file
80
ci/Jenkinsfile.tests
Normal file
@ -0,0 +1,80 @@
|
||||
library 'status-jenkins-lib@v1.7.0'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'linux && nix-2.11 && x86_64'
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
/* Go requires a certain directory structure */
|
||||
checkoutToSubdirectory('src/github.com/waku-org/go-waku')
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '30',
|
||||
))
|
||||
}
|
||||
|
||||
environment {
|
||||
TARGET = 'tests'
|
||||
REPO = "${env.WORKSPACE}/src/github.com/waku-org/go-waku"
|
||||
GOCACHE = "${env.WORKSPACE_TMP}/go-build"
|
||||
GOPATH = "${env.WORKSPACE}/go"
|
||||
PATH = "${env.PATH}:${env.GOPATH}/bin"
|
||||
/* Necesary to avoid cache poisoning by other builds. */
|
||||
GOLANGCI_LINT_CACHE = "${env.WORKSPACE_TMP}/golangci-lint"
|
||||
/* Ganache config */
|
||||
GANACHE_RPC_PORT = "${8989 + env.EXECUTOR_NUMBER.toInteger()}"
|
||||
GANACHE_MNEMONIC = 'swim relax risk shy chimney please usual search industry board music segment'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Lint') {
|
||||
steps { script { dir(env.REPO) {
|
||||
nix.develop('make lint', pure: false)
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
steps { script { dir(env.REPO) {
|
||||
nix.develop('make test-ci', pure: false)
|
||||
} } }
|
||||
}
|
||||
|
||||
stage('Ganache') {
|
||||
steps { script {
|
||||
ganache = docker.image(
|
||||
'trufflesuite/ganache:v7.4.1'
|
||||
).run(
|
||||
"-p 127.0.0.1:${env.GANACHE_RPC_PORT}:8545",
|
||||
"-m='${GANACHE_MNEMONIC}'"
|
||||
)
|
||||
} }
|
||||
}
|
||||
|
||||
stage('On-chain tests') {
|
||||
environment {
|
||||
GANACHE_NETWORK_RPC_URL = "ws://localhost:${env.GANACHE_RPC_PORT}"
|
||||
}
|
||||
steps { script { dir(env.REPO) {
|
||||
nix.develop('make test-onchain', pure: false)
|
||||
} } }
|
||||
}
|
||||
}
|
||||
post {
|
||||
always { script { /* No artifact but a PKG_URL is necessary. */
|
||||
env.PKG_URL = "${currentBuild.absoluteUrl}consoleText"
|
||||
} }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
cleanup { script {
|
||||
cleanWs()
|
||||
catchError {
|
||||
ganache.stop()
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,6 @@ import (
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
"github.com/waku-org/go-waku/waku/cliutils"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -26,19 +25,6 @@ var (
|
||||
Destination: &options.Address,
|
||||
EnvVars: []string{"WAKUNODE2_ADDRESS"},
|
||||
})
|
||||
MaxPeerConnections = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "max-connections",
|
||||
Value: 50,
|
||||
Usage: "Maximum allowed number of libp2p connections.",
|
||||
Destination: &options.MaxPeerConnections,
|
||||
EnvVars: []string{"WAKUNODE2_MAX_CONNECTIONS"},
|
||||
})
|
||||
PeerStoreCapacity = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "peer-store-capacity",
|
||||
Usage: "Maximum stored peers in the peerstore.",
|
||||
Destination: &options.PeerStoreCapacity,
|
||||
EnvVars: []string{"WAKUNODE2_PEERSTORE_CAPACITY"},
|
||||
})
|
||||
WebsocketSupport = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "websocket-support",
|
||||
Aliases: []string{"ws"},
|
||||
@ -93,11 +79,11 @@ var (
|
||||
Destination: &options.Websocket.CertPath,
|
||||
EnvVars: []string{"WAKUNODE2_WEBSOCKET_SECURE_CERT_PATH"},
|
||||
})
|
||||
DNS4DomainName = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Dns4DomainName = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "dns4-domain-name",
|
||||
Value: "",
|
||||
Usage: "The domain name resolving to the node's public IPv4 address",
|
||||
Destination: &options.DNS4DomainName,
|
||||
Destination: &options.Dns4DomainName,
|
||||
EnvVars: []string{"WAKUNODE2_WEBSOCKET_DNS4_DOMAIN_NAME"},
|
||||
})
|
||||
NodeKey = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{
|
||||
@ -122,12 +108,15 @@ var (
|
||||
Destination: &options.KeyPasswd,
|
||||
EnvVars: []string{"WAKUNODE2_KEY_PASSWORD"},
|
||||
})
|
||||
ClusterID = altsrc.NewUintFlag(&cli.UintFlag{
|
||||
Name: "cluster-id",
|
||||
Value: 0,
|
||||
Usage: "Cluster id that the node is running in. Node in a different cluster id is disconnected.",
|
||||
Destination: &options.ClusterID,
|
||||
EnvVars: []string{"WAKUNODE2_CLUSTER_ID"},
|
||||
GenerateKey = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "generate-key",
|
||||
Usage: "Generate private key file at path specified in --key-file with the password defined by --key-password",
|
||||
Destination: &options.GenerateKey,
|
||||
})
|
||||
Overwrite = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "overwrite",
|
||||
Usage: "When generating a keyfile, overwrite the nodekey file if it already exists",
|
||||
Destination: &options.Overwrite,
|
||||
})
|
||||
StaticNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
|
||||
Name: "staticnode",
|
||||
@ -185,28 +174,6 @@ var (
|
||||
Destination: &options.CircuitRelay,
|
||||
EnvVars: []string{"WAKUNODE2_CIRCUIT_RELAY"},
|
||||
})
|
||||
ForceReachability = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "force-reachability",
|
||||
Usage: "Force the node reachability. WARNING: This flag is created for testing circuit relay and is not meant to be used in production. Use 'public' or 'private'",
|
||||
Value: "",
|
||||
Hidden: true,
|
||||
Destination: &options.ForceReachability,
|
||||
EnvVars: []string{"WAKUNODE2_REACHABILITY"},
|
||||
})
|
||||
ResourceScalingMemoryPercent = altsrc.NewFloat64Flag(&cli.Float64Flag{
|
||||
Name: "resource-scaling-memory-percentage",
|
||||
Usage: "Determines the percentage of total accessible memory that wil be dedicated to go-waku. A dedicated node with a lot of RAM could allocate 25% or more memory to go-waku",
|
||||
Value: 25,
|
||||
Destination: &options.ResourceScalingMemoryPercent,
|
||||
EnvVars: []string{"WAKUNODE2_RESOURCE_MEMORY_PERCENTAGE"},
|
||||
})
|
||||
ResourceScalingFDPercent = altsrc.NewFloat64Flag(&cli.Float64Flag{
|
||||
Name: "resource-scaling-fd-percentage",
|
||||
Usage: "Determines the percentage of total file descriptors that wil be dedicated to go-waku.",
|
||||
Value: 50,
|
||||
Destination: &options.ResourceScalingFDPercent,
|
||||
EnvVars: []string{"WAKUNODE2_RESOURCE_FD_PERCENTAGE"},
|
||||
})
|
||||
LogLevel = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{
|
||||
Name: "log-level",
|
||||
Aliases: []string{"l"},
|
||||
@ -235,18 +202,11 @@ var (
|
||||
})
|
||||
AgentString = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "agent-string",
|
||||
Value: node.UserAgent,
|
||||
Value: "go-waku",
|
||||
Usage: "client id to advertise",
|
||||
Destination: &options.UserAgent,
|
||||
EnvVars: []string{"WAKUNODE2_AGENT_STRING"},
|
||||
})
|
||||
IPColocationLimit = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "ip-colocation-limit",
|
||||
Value: node.DefaultMaxConnectionsPerIP,
|
||||
Usage: "max number of allowed peers from the same IP. Set it to 0 to remove the limitation.",
|
||||
Destination: &options.IPColocationLimit,
|
||||
EnvVars: []string{"WAKUNODE2_IP_COLOCATION_LIMIT"},
|
||||
})
|
||||
Relay = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "relay",
|
||||
Value: true,
|
||||
@ -255,23 +215,11 @@ var (
|
||||
EnvVars: []string{"WAKUNODE2_RELAY"},
|
||||
})
|
||||
Topics = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{
|
||||
Name: "topic",
|
||||
Usage: "Default topic to subscribe to. Argument may be repeated. Deprecated! Please use pubsub-topic and/or content-topic instead.",
|
||||
Name: "topics",
|
||||
Usage: "List of topics to listen",
|
||||
Destination: &options.Relay.Topics,
|
||||
EnvVars: []string{"WAKUNODE2_TOPICS"},
|
||||
})
|
||||
PubSubTopics = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{
|
||||
Name: "pubsub-topic",
|
||||
Usage: "Default pubsub topic to subscribe to. Argument may be repeated.",
|
||||
Destination: &options.Relay.PubSubTopics,
|
||||
EnvVars: []string{"WAKUNODE2_PUBSUB_TOPICS"},
|
||||
})
|
||||
ContentTopics = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{
|
||||
Name: "content-topic",
|
||||
Usage: "Default content topic to subscribe to. Argument may be repeated.",
|
||||
Destination: &options.Relay.ContentTopics,
|
||||
EnvVars: []string{"WAKUNODE2_CONTENT_TOPICS"},
|
||||
})
|
||||
ProtectedTopics = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
|
||||
Name: "protected-topic",
|
||||
Usage: "Topics and its public key to be used for message validation, topic:pubkey. Argument may be repeated.",
|
||||
@ -294,13 +242,6 @@ var (
|
||||
Destination: &options.Relay.MinRelayPeersToPublish,
|
||||
EnvVars: []string{"WAKUNODE2_MIN_RELAY_PEERS_TO_PUBLISH"},
|
||||
})
|
||||
MaxRelayMsgSize = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "max-msg-size",
|
||||
Value: "150KB",
|
||||
Usage: "Maximum message size. Supported formats are B, KiB, KB, MiB. If no suffix, default is bytes",
|
||||
Destination: &options.Relay.MaxMsgSize,
|
||||
EnvVars: []string{"WAKUNODE2_MAX_RELAY_MSG_SIZE"},
|
||||
})
|
||||
StoreNodeFlag = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
|
||||
Name: "storenode",
|
||||
Usage: "Multiaddr of a peer that supports store protocol. Option may be repeated",
|
||||
@ -336,12 +277,13 @@ var (
|
||||
Destination: &options.Store.DatabaseURL,
|
||||
EnvVars: []string{"WAKUNODE2_STORE_MESSAGE_DB_URL"},
|
||||
})
|
||||
StoreMessageDBMigration = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "store-message-db-migration",
|
||||
Usage: "Enable database migration at start.",
|
||||
Destination: &options.Store.Migration,
|
||||
Value: true,
|
||||
EnvVars: []string{"WAKUNODE2_STORE_MESSAGE_DB_MIGRATION"},
|
||||
StoreResumePeer = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
|
||||
Name: "store-resume-peer",
|
||||
Usage: "Peer multiaddress to resume the message store at boot. Option may be repeated",
|
||||
Value: &cliutils.MultiaddrSlice{
|
||||
Values: &options.Store.ResumeNodes,
|
||||
},
|
||||
EnvVars: []string{"WAKUNODE2_STORE_RESUME_PEER"},
|
||||
})
|
||||
FilterFlag = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "filter",
|
||||
@ -364,6 +306,26 @@ var (
|
||||
Destination: &options.Filter.Timeout,
|
||||
EnvVars: []string{"WAKUNODE2_FILTER_TIMEOUT"},
|
||||
})
|
||||
FilterLegacyFlag = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "legacy-filter",
|
||||
Usage: "Use filter protocol (legacy)",
|
||||
Destination: &options.Filter.UseV1,
|
||||
EnvVars: []string{"WAKUNODE2_USE_LEGACY_FILTER"},
|
||||
})
|
||||
FilterLegacyLightClient = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "legacy-filter-light-client",
|
||||
Usage: "Don't accept legacy filter subscribers",
|
||||
Destination: &options.Filter.DisableFullNode,
|
||||
EnvVars: []string{"WAKUNODE2_LEGACY_FILTER_LIGHT_CLIENT"},
|
||||
})
|
||||
FilterLegacyNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
|
||||
Name: "legacy-filternode",
|
||||
Usage: "Multiaddr of a peer that supports legacy filter protocol. Option may be repeated",
|
||||
Value: &cliutils.MultiaddrSlice{
|
||||
Values: &options.Filter.NodesV1,
|
||||
},
|
||||
EnvVars: []string{"WAKUNODE2_LEGACY_FILTERNODE"},
|
||||
})
|
||||
LightPush = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "lightpush",
|
||||
Usage: "Enable lightpush protocol",
|
||||
@ -419,8 +381,8 @@ var (
|
||||
})
|
||||
RendezvousServer = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rendezvous-server",
|
||||
Usage: "Enable rendezvous protocol so other peers can use this node for discovery",
|
||||
Destination: &options.Rendezvous.Enable,
|
||||
Usage: "Enable rendezvous protocol server so other peers can use this node for discovery",
|
||||
Destination: &options.Rendezvous.Server,
|
||||
EnvVars: []string{"WAKUNODE2_RENDEZVOUS_SERVER"},
|
||||
})
|
||||
PeerExchange = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
@ -445,7 +407,7 @@ var (
|
||||
})
|
||||
DNSDiscoveryUrl = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{
|
||||
Name: "dns-discovery-url",
|
||||
Usage: "URL for DNS node list in format 'enrtree://<key>@<fqdn>'. Option may be repeated",
|
||||
Usage: "URL for DNS node list in format 'enrtree://<key>@<fqdn>'",
|
||||
Destination: &options.DNSDiscovery.URLs,
|
||||
EnvVars: []string{"WAKUNODE2_DNS_DISCOVERY_URL"},
|
||||
})
|
||||
@ -479,6 +441,47 @@ var (
|
||||
Destination: &options.Metrics.Port,
|
||||
EnvVars: []string{"WAKUNODE2_METRICS_SERVER_PORT"},
|
||||
})
|
||||
RPCFlag = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rpc",
|
||||
Usage: "Enable the rpc server",
|
||||
Destination: &options.RPCServer.Enable,
|
||||
EnvVars: []string{"WAKUNODE2_RPC"},
|
||||
})
|
||||
RPCPort = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "rpc-port",
|
||||
Value: 8545,
|
||||
Usage: "Listening port of the rpc server",
|
||||
Destination: &options.RPCServer.Port,
|
||||
EnvVars: []string{"WAKUNODE2_RPC_PORT"},
|
||||
})
|
||||
RPCAddress = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "rpc-address",
|
||||
Value: "127.0.0.1",
|
||||
Usage: "Listening address of the rpc server",
|
||||
Destination: &options.RPCServer.Address,
|
||||
EnvVars: []string{"WAKUNODE2_RPC_ADDRESS"},
|
||||
})
|
||||
RPCRelayCacheCapacity = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "rpc-relay-cache-capacity",
|
||||
Value: 30,
|
||||
Usage: "Capacity of the Relay REST API message cache",
|
||||
Destination: &options.RPCServer.RelayCacheCapacity,
|
||||
EnvVars: []string{"WAKUNODE2_RPC_RELAY_CACHE_CAPACITY"},
|
||||
})
|
||||
RPCAdmin = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rpc-admin",
|
||||
Value: false,
|
||||
Usage: "Enable access to JSON-RPC Admin API",
|
||||
Destination: &options.RPCServer.Admin,
|
||||
EnvVars: []string{"WAKUNODE2_RPC_ADMIN"},
|
||||
})
|
||||
RPCPrivate = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rpc-private",
|
||||
Value: false,
|
||||
Usage: "Enable access to JSON-RPC Private API",
|
||||
Destination: &options.RPCServer.Private,
|
||||
EnvVars: []string{"WAKUNODE2_RPC_PRIVATE"},
|
||||
})
|
||||
RESTFlag = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rest",
|
||||
Usage: "Enable Waku REST HTTP server",
|
||||
@ -501,18 +504,11 @@ var (
|
||||
})
|
||||
RESTRelayCacheCapacity = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "rest-relay-cache-capacity",
|
||||
Value: 1000,
|
||||
Value: 30,
|
||||
Usage: "Capacity of the Relay REST API message cache",
|
||||
Destination: &options.RESTServer.RelayCacheCapacity,
|
||||
EnvVars: []string{"WAKUNODE2_REST_RELAY_CACHE_CAPACITY"},
|
||||
})
|
||||
RESTFilterCacheCapacity = altsrc.NewIntFlag(&cli.IntFlag{
|
||||
Name: "rest-filter-cache-capacity",
|
||||
Value: 30,
|
||||
Usage: "Capacity of the Filter REST API message cache",
|
||||
Destination: &options.RESTServer.FilterCacheCapacity,
|
||||
EnvVars: []string{"WAKUNODE2_REST_FILTER_CACHE_CAPACITY"},
|
||||
})
|
||||
RESTAdmin = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rest-admin",
|
||||
Value: false,
|
||||
@ -520,6 +516,13 @@ var (
|
||||
Destination: &options.RESTServer.Admin,
|
||||
EnvVars: []string{"WAKUNODE2_REST_ADMIN"},
|
||||
})
|
||||
RESTPrivate = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "rest-private",
|
||||
Value: false,
|
||||
Usage: "Enable access to REST HTTP Private API",
|
||||
Destination: &options.RESTServer.Private,
|
||||
EnvVars: []string{"WAKUNODE2_REST_PRIVATE"},
|
||||
})
|
||||
PProf = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "pprof",
|
||||
Usage: "provides runtime profiling data at /debug/pprof in both REST and RPC servers if they're enabled",
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
package keygen
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Command generates a key file used to generate the node's peerID, encrypted with an optional password
|
||||
var Command = cli.Command{
|
||||
Name: "generate-key",
|
||||
Usage: "Generate private key file at path specified in --key-file with the password defined by --key-password",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
if err := generateKeyFile(Options.KeyFile, []byte(Options.KeyPasswd), Options.Overwrite); err != nil {
|
||||
utils.Logger().Fatal("could not write keyfile", zap.Error(err))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
KeyFile,
|
||||
KeyPassword,
|
||||
Overwrite,
|
||||
},
|
||||
}
|
||||
|
||||
func checkForFileExistence(path string, overwrite bool) error {
|
||||
_, err := os.Stat(path)
|
||||
|
||||
if err == nil && !overwrite {
|
||||
return fmt.Errorf("%s already exists. Use --overwrite to overwrite the file", path)
|
||||
}
|
||||
|
||||
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generatePrivateKey() ([]byte, error) {
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return key.D.Bytes(), nil
|
||||
}
|
||||
|
||||
func writeKeyFile(path string, key []byte, passwd []byte) error {
|
||||
encryptedK, err := keystore.EncryptDataV3(key, passwd, keystore.StandardScryptN, keystore.StandardScryptP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
output, err := json.Marshal(encryptedK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(path, output, 0600)
|
||||
}
|
||||
|
||||
func generateKeyFile(path string, passwd []byte, overwrite bool) error {
|
||||
if err := checkForFileExistence(path, overwrite); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := generatePrivateKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeKeyFile(path, key, passwd)
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package keygen
|
||||
|
||||
import (
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
)
|
||||
|
||||
// Options contain the settings used for generating a key file
|
||||
var Options GenerateKeyOptions
|
||||
|
||||
var (
|
||||
// KeyFile is a flag that contains the path where the node key will be written
|
||||
KeyFile = altsrc.NewPathFlag(&cli.PathFlag{
|
||||
Name: "key-file",
|
||||
Value: "./nodekey",
|
||||
Usage: "Path to a file containing the private key for the P2P node",
|
||||
Destination: &Options.KeyFile,
|
||||
EnvVars: []string{"WAKUNODE2_KEY_FILE"},
|
||||
})
|
||||
// KeyPassword is a flag to set the password used to encrypt the file
|
||||
KeyPassword = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "key-password",
|
||||
Value: "secret",
|
||||
Usage: "Password used for the private key file",
|
||||
Destination: &Options.KeyPasswd,
|
||||
EnvVars: []string{"WAKUNODE2_KEY_PASSWORD"},
|
||||
})
|
||||
// Overwrite is a flag used to overwrite an existing key file
|
||||
Overwrite = altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "overwrite",
|
||||
Value: false,
|
||||
Usage: "Overwrite the nodekey file if it already exists",
|
||||
Destination: &Options.Overwrite,
|
||||
})
|
||||
)
|
||||
@ -1,9 +0,0 @@
|
||||
package keygen
|
||||
|
||||
// GenerateKeyOptions contains all the settings that can be used when generating
|
||||
// a keyfile with the generate-key command
|
||||
type GenerateKeyOptions struct {
|
||||
KeyFile string
|
||||
KeyPasswd string
|
||||
Overwrite bool
|
||||
}
|
||||
@ -5,14 +5,11 @@ import (
|
||||
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
"github.com/waku-org/go-waku/cmd/waku/keygen"
|
||||
"github.com/waku-org/go-waku/cmd/waku/rlngenerate"
|
||||
"github.com/waku-org/go-waku/waku"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var options NodeOptions
|
||||
var options waku.Options
|
||||
|
||||
func main() {
|
||||
// Defaults
|
||||
@ -23,8 +20,6 @@ func main() {
|
||||
&cli.StringFlag{Name: "config-file", Usage: "loads configuration from a TOML file (cmd-line parameters take precedence)"},
|
||||
TcpPort,
|
||||
Address,
|
||||
MaxPeerConnections,
|
||||
PeerStoreCapacity,
|
||||
WebsocketSupport,
|
||||
WebsocketPort,
|
||||
WebsocketSecurePort,
|
||||
@ -32,11 +27,12 @@ func main() {
|
||||
WebsocketSecureSupport,
|
||||
WebsocketSecureKeyPath,
|
||||
WebsocketSecureCertPath,
|
||||
DNS4DomainName,
|
||||
Dns4DomainName,
|
||||
NodeKey,
|
||||
KeyFile,
|
||||
KeyPassword,
|
||||
ClusterID,
|
||||
GenerateKey,
|
||||
Overwrite,
|
||||
StaticNode,
|
||||
KeepAlive,
|
||||
PersistPeers,
|
||||
@ -45,31 +41,27 @@ func main() {
|
||||
ExtMultiaddresses,
|
||||
ShowAddresses,
|
||||
CircuitRelay,
|
||||
ForceReachability,
|
||||
ResourceScalingMemoryPercent,
|
||||
ResourceScalingFDPercent,
|
||||
IPColocationLimit,
|
||||
LogLevel,
|
||||
LogEncoding,
|
||||
LogOutput,
|
||||
AgentString,
|
||||
Relay,
|
||||
Topics,
|
||||
ContentTopics,
|
||||
PubSubTopics,
|
||||
ProtectedTopics,
|
||||
RelayPeerExchange,
|
||||
MinRelayPeersToPublish,
|
||||
MaxRelayMsgSize,
|
||||
StoreNodeFlag,
|
||||
StoreFlag,
|
||||
StoreMessageDBURL,
|
||||
StoreMessageRetentionTime,
|
||||
StoreMessageRetentionCapacity,
|
||||
StoreMessageDBMigration,
|
||||
StoreResumePeer,
|
||||
FilterFlag,
|
||||
FilterNode,
|
||||
FilterTimeout,
|
||||
FilterLegacyFlag,
|
||||
FilterLegacyNode,
|
||||
FilterLegacyLightClient,
|
||||
LightPush,
|
||||
LightPushNode,
|
||||
Discv5Discovery,
|
||||
@ -87,12 +79,18 @@ func main() {
|
||||
MetricsServer,
|
||||
MetricsServerAddress,
|
||||
MetricsServerPort,
|
||||
RPCFlag,
|
||||
RPCPort,
|
||||
RPCAddress,
|
||||
RPCRelayCacheCapacity,
|
||||
RPCAdmin,
|
||||
RPCPrivate,
|
||||
RESTFlag,
|
||||
RESTAddress,
|
||||
RESTPort,
|
||||
RESTRelayCacheCapacity,
|
||||
RESTFilterCacheCapacity,
|
||||
RESTAdmin,
|
||||
RESTPrivate,
|
||||
PProf,
|
||||
}
|
||||
|
||||
@ -110,22 +108,9 @@ func main() {
|
||||
Before: altsrc.InitInputSourceWithContext(cliFlags, altsrc.NewTomlSourceFromFlagFunc("config-file")),
|
||||
Flags: cliFlags,
|
||||
Action: func(c *cli.Context) error {
|
||||
err := Execute(options)
|
||||
if err != nil {
|
||||
utils.Logger().Error("failure while executing wakunode", zap.Error(err))
|
||||
switch e := err.(type) {
|
||||
case cli.ExitCoder:
|
||||
return e
|
||||
case error:
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
}
|
||||
waku.Execute(options)
|
||||
return nil
|
||||
},
|
||||
Commands: []*cli.Command{
|
||||
&keygen.Command,
|
||||
&rlngenerate.Command,
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//go:build gowaku_no_rln
|
||||
// +build gowaku_no_rln
|
||||
//go:build !gowaku_rln
|
||||
// +build !gowaku_rln
|
||||
|
||||
package main
|
||||
|
||||
582
cmd/waku/node.go
582
cmd/waku/node.go
@ -1,582 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
|
||||
"github.com/pbnjay/memory"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
dbutils "github.com/waku-org/go-waku/waku/persistence/utils"
|
||||
"github.com/waku-org/go-waku/waku/v2/dnsdisc"
|
||||
wakupeerstore "github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||
"github.com/waku-org/go-waku/waku/v2/rendezvous"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
dssql "github.com/ipfs/go-ds-sql"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
"github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p/config"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
|
||||
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoreds" // nolint: staticcheck
|
||||
ws "github.com/libp2p/go-libp2p/p2p/transport/websocket"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/waku-org/go-waku/cmd/waku/server/rest"
|
||||
"github.com/waku-org/go-waku/logging"
|
||||
"github.com/waku-org/go-waku/waku/metrics"
|
||||
"github.com/waku-org/go-waku/waku/persistence"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
wprotocol "github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_store"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/peer_exchange"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
func requiresDB(options NodeOptions) bool {
|
||||
return options.Store.Enable || options.Rendezvous.Enable
|
||||
}
|
||||
|
||||
func scalePerc(value float64) float64 {
|
||||
if value > 100 {
|
||||
return 100
|
||||
}
|
||||
|
||||
if value < 0.1 {
|
||||
return 0.1
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const dialTimeout = 7 * time.Second
|
||||
|
||||
func nonRecoverErrorMsg(format string, a ...any) error {
|
||||
err := fmt.Errorf(format, a...)
|
||||
return nonRecoverError(err)
|
||||
}
|
||||
|
||||
func nonRecoverError(err error) error {
|
||||
return cli.Exit(err.Error(), 166)
|
||||
}
|
||||
|
||||
// Execute starts a go-waku node with settings determined by the Options parameter
|
||||
func Execute(options NodeOptions) error {
|
||||
// Set encoding for logs (console, json, ...)
|
||||
// Note that libp2p reads the encoding from GOLOG_LOG_FMT env var.
|
||||
lvl, err := zapcore.ParseLevel(options.LogLevel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
utils.InitLogger(options.LogEncoding, options.LogOutput, "gowaku", lvl)
|
||||
|
||||
hostAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", options.Address, options.Port))
|
||||
if err != nil {
|
||||
return nonRecoverErrorMsg("invalid host address: %w", err)
|
||||
}
|
||||
|
||||
prvKey, err := getPrivKey(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p2pPrvKey := utils.EcdsaPrivKeyToSecp256k1PrivKey(prvKey)
|
||||
id, err := peer.IDFromPublicKey(p2pPrvKey.GetPublic())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := utils.Logger().With(logging.HostID("node", id))
|
||||
|
||||
var db *sql.DB
|
||||
var migrationFn func(*sql.DB, *zap.Logger) error
|
||||
if requiresDB(options) && options.Store.Migration {
|
||||
dbSettings := dbutils.DBSettings{}
|
||||
db, migrationFn, err = dbutils.ParseURL(options.Store.DatabaseURL, dbSettings, logger)
|
||||
if err != nil {
|
||||
return nonRecoverErrorMsg("could not connect to DB: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var metricsServer *metrics.Server
|
||||
if options.Metrics.Enable {
|
||||
metricsServer = metrics.NewMetricsServer(options.Metrics.Address, options.Metrics.Port, logger)
|
||||
go metricsServer.Start()
|
||||
}
|
||||
|
||||
nodeOpts := []node.WakuNodeOption{
|
||||
node.WithLogger(logger),
|
||||
node.WithLogLevel(lvl),
|
||||
node.WithPrivateKey(prvKey),
|
||||
node.WithHostAddress(hostAddr),
|
||||
node.WithKeepAlive(10*time.Second, options.KeepAlive),
|
||||
node.WithMaxPeerConnections(options.MaxPeerConnections),
|
||||
node.WithPrometheusRegisterer(prometheus.DefaultRegisterer),
|
||||
node.WithPeerStoreCapacity(options.PeerStoreCapacity),
|
||||
node.WithMaxConnectionsPerIP(options.IPColocationLimit),
|
||||
node.WithClusterID(uint16(options.ClusterID)),
|
||||
}
|
||||
if len(options.AdvertiseAddresses) != 0 {
|
||||
nodeOpts = append(nodeOpts, node.WithAdvertiseAddresses(options.AdvertiseAddresses...))
|
||||
}
|
||||
|
||||
if options.ExtIP != "" {
|
||||
ip := net.ParseIP(options.ExtIP)
|
||||
if ip == nil {
|
||||
return nonRecoverErrorMsg("could not set external IP address: invalid IP")
|
||||
}
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithExternalIP(ip))
|
||||
}
|
||||
|
||||
if options.DNS4DomainName != "" {
|
||||
nodeOpts = append(nodeOpts, node.WithDNS4Domain(options.DNS4DomainName))
|
||||
}
|
||||
|
||||
libp2pOpts := node.DefaultLibP2POptions
|
||||
|
||||
libp2pOpts = append(libp2pOpts, libp2p.PrometheusRegisterer(prometheus.DefaultRegisterer))
|
||||
|
||||
memPerc := scalePerc(options.ResourceScalingMemoryPercent)
|
||||
fdPerc := scalePerc(options.ResourceScalingFDPercent)
|
||||
limits := rcmgr.DefaultLimits // Default memory limit: 1/8th of total memory, minimum 128MB, maximum 1GB
|
||||
scaledLimits := limits.Scale(int64(float64(memory.TotalMemory())*memPerc/100), int(float64(getNumFDs())*fdPerc/100))
|
||||
resourceManager, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(scaledLimits))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not set resource limits: %w", err)
|
||||
}
|
||||
|
||||
libp2pOpts = append(libp2pOpts, libp2p.ResourceManager(resourceManager))
|
||||
libp2p.SetDefaultServiceLimits(&limits)
|
||||
|
||||
if len(options.AdvertiseAddresses) == 0 {
|
||||
libp2pOpts = append(libp2pOpts, libp2p.NATPortMap()) // Attempt to open ports using uPNP for NATed hosts.)
|
||||
}
|
||||
|
||||
// Node can be a circuit relay server
|
||||
if options.CircuitRelay {
|
||||
libp2pOpts = append(libp2pOpts, libp2p.EnableRelayService())
|
||||
}
|
||||
|
||||
if options.ForceReachability != "" {
|
||||
libp2pOpts = append(libp2pOpts, libp2p.EnableRelay())
|
||||
nodeOpts = append(nodeOpts, node.WithCircuitRelayParams(2*time.Second, 2*time.Second))
|
||||
if options.ForceReachability == "private" {
|
||||
logger.Warn("node forced to be unreachable!")
|
||||
libp2pOpts = append(libp2pOpts, libp2p.ForceReachabilityPrivate())
|
||||
} else if options.ForceReachability == "public" {
|
||||
logger.Warn("node forced to be publicly reachable!")
|
||||
libp2pOpts = append(libp2pOpts, libp2p.ForceReachabilityPublic())
|
||||
} else {
|
||||
return nonRecoverErrorMsg("invalid reachability value")
|
||||
}
|
||||
}
|
||||
|
||||
if options.UserAgent != "" {
|
||||
libp2pOpts = append(libp2pOpts, libp2p.UserAgent(options.UserAgent))
|
||||
}
|
||||
|
||||
if options.Websocket.Enable {
|
||||
nodeOpts = append(nodeOpts, node.WithWebsockets(options.Websocket.Address, options.Websocket.WSPort))
|
||||
}
|
||||
|
||||
if options.Websocket.Secure {
|
||||
nodeOpts = append(nodeOpts, node.WithSecureWebsockets(options.Websocket.Address, options.Websocket.WSSPort, options.Websocket.CertPath, options.Websocket.KeyPath))
|
||||
}
|
||||
|
||||
if options.ShowAddresses {
|
||||
printListeningAddresses(ctx, nodeOpts, options)
|
||||
return nil
|
||||
}
|
||||
|
||||
if options.Store.Enable && options.PersistPeers {
|
||||
// Create persistent peerstore
|
||||
queries, err := dbutils.NewQueries("peerstore", db)
|
||||
if err != nil {
|
||||
return nonRecoverErrorMsg("could not setup persistent peerstore database: %w", err)
|
||||
|
||||
}
|
||||
|
||||
datastore := dssql.NewDatastore(db, queries)
|
||||
opts := pstoreds.DefaultOpts()
|
||||
peerStore, err := pstoreds.NewPeerstore(ctx, datastore, opts)
|
||||
if err != nil {
|
||||
return nonRecoverErrorMsg("could not create persistent peerstore: %w", err)
|
||||
}
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithPeerStore(peerStore))
|
||||
}
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithLibP2POptions(libp2pOpts...))
|
||||
nodeOpts = append(nodeOpts, node.WithNTP())
|
||||
|
||||
maxMsgSize := parseMsgSizeConfig(options.Relay.MaxMsgSize)
|
||||
|
||||
if options.Relay.Enable {
|
||||
var wakurelayopts []pubsub.Option
|
||||
wakurelayopts = append(wakurelayopts, pubsub.WithPeerExchange(options.Relay.PeerExchange))
|
||||
wakurelayopts = append(wakurelayopts, pubsub.WithMaxMessageSize(maxMsgSize))
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithWakuRelayAndMinPeers(options.Relay.MinRelayPeersToPublish, wakurelayopts...))
|
||||
nodeOpts = append(nodeOpts, node.WithMaxMsgSize(maxMsgSize))
|
||||
}
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithWakuFilterLightNode())
|
||||
|
||||
if options.Filter.Enable {
|
||||
nodeOpts = append(nodeOpts, node.WithWakuFilterFullNode(filter.WithTimeout(options.Filter.Timeout)))
|
||||
}
|
||||
|
||||
var dbStore *persistence.DBStore
|
||||
if requiresDB(options) {
|
||||
dbOptions := []persistence.DBOption{
|
||||
persistence.WithDB(db),
|
||||
persistence.WithRetentionPolicy(options.Store.RetentionMaxMessages, options.Store.RetentionTime),
|
||||
}
|
||||
|
||||
if options.Store.Migration {
|
||||
dbOptions = append(dbOptions, persistence.WithMigrations(migrationFn)) // TODO: refactor migrations out of DBStore, or merge DBStore with rendezvous DB
|
||||
}
|
||||
|
||||
dbStore, err = persistence.NewDBStore(prometheus.DefaultRegisterer, logger, dbOptions...)
|
||||
if err != nil {
|
||||
return nonRecoverErrorMsg("error setting up db store: %w", err)
|
||||
}
|
||||
|
||||
nodeOpts = append(nodeOpts, node.WithMessageProvider(dbStore))
|
||||
}
|
||||
|
||||
if options.Store.Enable {
|
||||
nodeOpts = append(nodeOpts, node.WithWakuStore())
|
||||
nodeOpts = append(nodeOpts, node.WithMessageProvider(dbStore))
|
||||
}
|
||||
|
||||
if options.LightPush.Enable {
|
||||
nodeOpts = append(nodeOpts, node.WithLightPush())
|
||||
}
|
||||
|
||||
if options.PeerExchange.Enable {
|
||||
nodeOpts = append(nodeOpts, node.WithPeerExchange())
|
||||
}
|
||||
|
||||
if options.Rendezvous.Enable {
|
||||
rdb := rendezvous.NewDB(db, logger)
|
||||
nodeOpts = append(nodeOpts, node.WithRendezvous(rdb))
|
||||
}
|
||||
|
||||
utils.Logger().Info("Version details ", zap.String("version", node.Version), zap.String("commit", node.GitCommit))
|
||||
|
||||
if err = checkForRLN(logger, options, &nodeOpts); err != nil {
|
||||
return nonRecoverError(err)
|
||||
}
|
||||
|
||||
var discoveredNodes []dnsdisc.DiscoveredNode
|
||||
if options.DNSDiscovery.Enable {
|
||||
if len(options.DNSDiscovery.URLs.Value()) == 0 {
|
||||
return nonRecoverErrorMsg("DNS discovery URL is required")
|
||||
}
|
||||
discoveredNodes = node.GetNodesFromDNSDiscovery(logger, ctx, options.DNSDiscovery.Nameserver, options.DNSDiscovery.URLs.Value())
|
||||
}
|
||||
if options.DiscV5.Enable {
|
||||
discv5Opts, err := node.GetDiscv5Option(discoveredNodes, options.DiscV5.Nodes.Value(), options.DiscV5.Port, options.DiscV5.AutoUpdate)
|
||||
if err != nil {
|
||||
logger.Fatal("parsing ENR", zap.Error(err))
|
||||
}
|
||||
nodeOpts = append(nodeOpts, discv5Opts)
|
||||
}
|
||||
|
||||
//Process pubSub and contentTopics specified and arrive at all corresponding pubSubTopics
|
||||
pubSubTopicMap, err := processTopics(options)
|
||||
if err != nil {
|
||||
return nonRecoverError(err)
|
||||
}
|
||||
|
||||
pubSubTopicMapKeys := make([]string, 0, len(pubSubTopicMap))
|
||||
for k := range pubSubTopicMap {
|
||||
pubSubTopicMapKeys = append(pubSubTopicMapKeys, k)
|
||||
}
|
||||
|
||||
rs, err := wprotocol.TopicsToRelayShards(pubSubTopicMapKeys...)
|
||||
if err == nil {
|
||||
if len(rs) == 1 {
|
||||
nodeOpts = append(nodeOpts, node.WithShards(rs[0].ShardIDs))
|
||||
} else {
|
||||
logger.Warn("could not set ENR shard info", zap.String("error", "invalid number of clusters found"), zap.Int("numClusters", len(rs)))
|
||||
}
|
||||
} else {
|
||||
logger.Warn("could not obtain list of shards", zap.Error(err))
|
||||
}
|
||||
|
||||
wakuNode, err := node.New(nodeOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not instantiate waku: %w", err)
|
||||
}
|
||||
|
||||
if err = wakuNode.Start(ctx); err != nil {
|
||||
return nonRecoverError(err)
|
||||
}
|
||||
|
||||
for _, d := range discoveredNodes {
|
||||
wakuNode.AddDiscoveredPeer(d.PeerID, d.PeerInfo.Addrs, wakupeerstore.DNSDiscovery, nil, d.ENR, true)
|
||||
}
|
||||
|
||||
//For now assuming that static peers added support/listen on all topics specified via commandLine.
|
||||
staticPeers := map[protocol.ID][]multiaddr.Multiaddr{
|
||||
legacy_store.StoreID_v20beta4: options.Store.Nodes,
|
||||
lightpush.LightPushID_v20beta1: options.LightPush.Nodes,
|
||||
rendezvous.RendezvousID: options.Rendezvous.Nodes,
|
||||
filter.FilterSubscribeID_v20beta1: options.Filter.Nodes,
|
||||
}
|
||||
for protocolID, peers := range staticPeers {
|
||||
if err = addStaticPeers(wakuNode, peers, pubSubTopicMapKeys, protocolID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if options.Relay.Enable {
|
||||
if err = handleRelayTopics(ctx, &wg, wakuNode, pubSubTopicMap); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range options.StaticNodes {
|
||||
go func(ctx context.Context, node multiaddr.Multiaddr) {
|
||||
ctx, cancel := context.WithTimeout(ctx, dialTimeout)
|
||||
defer cancel()
|
||||
err = wakuNode.DialPeerWithMultiAddress(ctx, node)
|
||||
if err != nil {
|
||||
logger.Error("dialing peer", zap.Error(err))
|
||||
}
|
||||
}(ctx, n)
|
||||
}
|
||||
|
||||
if options.DiscV5.Enable {
|
||||
if err = wakuNode.DiscV5().Start(ctx); err != nil {
|
||||
logger.Fatal("starting discovery v5", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve and connect to peer exchange peers
|
||||
if options.PeerExchange.Enable && options.PeerExchange.Node != nil {
|
||||
logger.Info("retrieving peer info via peer exchange protocol")
|
||||
|
||||
peerID, err := wakuNode.AddPeer([]multiaddr.Multiaddr{*options.PeerExchange.Node}, wakupeerstore.Static,
|
||||
pubSubTopicMapKeys, peer_exchange.PeerExchangeID_v20alpha1)
|
||||
if err != nil {
|
||||
logger.Error("adding peer exchange peer", logging.MultiAddrs("node", *options.PeerExchange.Node), zap.Error(err))
|
||||
} else {
|
||||
desiredOutDegree := wakuNode.Relay().Params().D
|
||||
if err = wakuNode.PeerExchange().Request(ctx, desiredOutDegree, peer_exchange.WithPeer(peerID)); err != nil {
|
||||
logger.Error("requesting peers via peer exchange", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var restServer *rest.WakuRest
|
||||
if options.RESTServer.Enable {
|
||||
wg.Add(1)
|
||||
restConfig := rest.RestConfig{Address: options.RESTServer.Address,
|
||||
Port: uint(options.RESTServer.Port),
|
||||
EnablePProf: options.PProf,
|
||||
EnableAdmin: options.RESTServer.Admin,
|
||||
RelayCacheCapacity: uint(options.RESTServer.RelayCacheCapacity),
|
||||
FilterCacheCapacity: uint(options.RESTServer.FilterCacheCapacity)}
|
||||
|
||||
restServer = rest.NewWakuRest(wakuNode, restConfig, logger)
|
||||
restServer.Start(ctx, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
logger.Info("Node setup complete")
|
||||
|
||||
// Wait for a SIGINT or SIGTERM signal
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-ch
|
||||
logger.Info("Received signal, shutting down...")
|
||||
|
||||
// shut the node down
|
||||
wakuNode.Stop()
|
||||
|
||||
if options.RESTServer.Enable {
|
||||
if err := restServer.Stop(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if options.Metrics.Enable {
|
||||
if err = metricsServer.Stop(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if db != nil {
|
||||
if err = db.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processTopics(options NodeOptions) (map[string][]string, error) {
|
||||
|
||||
//Using a map to avoid duplicate pub-sub topics that can result from autosharding
|
||||
// or same-topic being passed twice.
|
||||
pubSubTopicMap := make(map[string][]string)
|
||||
|
||||
for _, topic := range options.Relay.Topics.Value() {
|
||||
pubSubTopicMap[topic] = []string{}
|
||||
}
|
||||
|
||||
for _, topic := range options.Relay.PubSubTopics.Value() {
|
||||
pubSubTopicMap[topic] = []string{}
|
||||
}
|
||||
|
||||
//Get pubSub topics from contentTopics if they are as per autosharding
|
||||
for _, cTopic := range options.Relay.ContentTopics.Value() {
|
||||
contentTopic, err := wprotocol.StringToContentTopic(cTopic)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pTopic := wprotocol.GetShardFromContentTopic(contentTopic, wprotocol.GenerationZeroShardsCount)
|
||||
if _, ok := pubSubTopicMap[pTopic.String()]; !ok {
|
||||
pubSubTopicMap[pTopic.String()] = []string{}
|
||||
}
|
||||
pubSubTopicMap[pTopic.String()] = append(pubSubTopicMap[pTopic.String()], cTopic)
|
||||
}
|
||||
//If no topics are passed, then use default waku topic.
|
||||
if len(pubSubTopicMap) == 0 && options.ClusterID == 0 {
|
||||
pubSubTopicMap[relay.DefaultWakuTopic] = []string{}
|
||||
}
|
||||
|
||||
return pubSubTopicMap, nil
|
||||
}
|
||||
|
||||
func addStaticPeers(wakuNode *node.WakuNode, addresses []multiaddr.Multiaddr, pubSubTopics []string, protocols ...protocol.ID) error {
|
||||
for _, addr := range addresses {
|
||||
_, err := wakuNode.AddPeer([]multiaddr.Multiaddr{addr}, wakupeerstore.Static, pubSubTopics, protocols...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not add static peer: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadPrivateKeyFromFile(path string, passwd string) (*ecdsa.PrivateKey, error) {
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var encryptedK keystore.CryptoJSON
|
||||
err = json.Unmarshal(src, &encryptedK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pKey, err := keystore.DecryptDataV3(encryptedK, passwd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return crypto.ToECDSA(pKey)
|
||||
}
|
||||
|
||||
func getPrivKey(options NodeOptions) (*ecdsa.PrivateKey, error) {
|
||||
var prvKey *ecdsa.PrivateKey
|
||||
// get private key from nodeKey or keyFile
|
||||
if options.NodeKey != nil {
|
||||
prvKey = options.NodeKey
|
||||
} else {
|
||||
if _, err := os.Stat(options.KeyFile); err == nil {
|
||||
if prvKey, err = loadPrivateKeyFromFile(options.KeyFile, options.KeyPasswd); err != nil {
|
||||
return nil, fmt.Errorf("could not read keyfile: %w", err)
|
||||
}
|
||||
} else {
|
||||
if os.IsNotExist(err) {
|
||||
if prvKey, err = crypto.GenerateKey(); err != nil {
|
||||
return nil, fmt.Errorf("error generating key: %w", err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("could not read keyfile: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return prvKey, nil
|
||||
}
|
||||
|
||||
func printListeningAddresses(ctx context.Context, nodeOpts []node.WakuNodeOption, options NodeOptions) {
|
||||
params := new(node.WakuNodeParameters)
|
||||
for _, opt := range nodeOpts {
|
||||
err := opt(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var libp2pOpts []config.Option
|
||||
libp2pOpts = append(libp2pOpts,
|
||||
params.Identity(),
|
||||
libp2p.ListenAddrs(params.MultiAddresses()...),
|
||||
)
|
||||
|
||||
if options.Websocket.Secure {
|
||||
transports := libp2p.ChainOptions(
|
||||
libp2p.Transport(tcp.NewTCPTransport),
|
||||
libp2p.Transport(ws.New, ws.WithTLSConfig(params.TLSConfig())),
|
||||
)
|
||||
libp2pOpts = append(libp2pOpts, transports)
|
||||
}
|
||||
|
||||
addrFactory := params.AddressFactory()
|
||||
if addrFactory != nil {
|
||||
libp2pOpts = append(libp2pOpts, libp2p.AddrsFactory(addrFactory))
|
||||
}
|
||||
|
||||
h, err := libp2p.New(libp2pOpts...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hostAddrs := utils.EncapsulatePeerID(h.ID(), h.Addrs()...)
|
||||
for _, addr := range hostAddrs {
|
||||
fmt.Println(addr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func parseMsgSizeConfig(msgSizeConfig string) int {
|
||||
|
||||
msgSize, err := humanize.ParseBytes(msgSizeConfig)
|
||||
if err != nil {
|
||||
msgSize = 0
|
||||
}
|
||||
return int(msgSize)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
//go:build gowaku_no_rln
|
||||
// +build gowaku_no_rln
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuNodeOption) error {
|
||||
// Do nothing
|
||||
return nil
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-zerokit-rln/rln"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuNodeOption) error {
|
||||
if options.RLNRelay.Enable {
|
||||
if !options.Relay.Enable {
|
||||
return errors.New("waku relay is required to enable RLN relay")
|
||||
}
|
||||
|
||||
if !options.RLNRelay.Dynamic {
|
||||
*nodeOpts = append(*nodeOpts, node.WithStaticRLNRelay((*rln.MembershipIndex)(options.RLNRelay.MembershipIndex), nil))
|
||||
} else {
|
||||
// TODO: too many parameters in this function
|
||||
// consider passing a config struct instead
|
||||
*nodeOpts = append(*nodeOpts, node.WithDynamicRLNRelay(
|
||||
options.RLNRelay.CredentialsPath,
|
||||
options.RLNRelay.CredentialsPassword,
|
||||
options.RLNRelay.TreePath,
|
||||
options.RLNRelay.MembershipContractAddress,
|
||||
options.RLNRelay.MembershipIndex,
|
||||
nil,
|
||||
options.RLNRelay.ETHClientAddress,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
wprotocol "github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/rendezvous"
|
||||
)
|
||||
|
||||
func handleRelayTopics(ctx context.Context, wg *sync.WaitGroup, wakuNode *node.WakuNode, pubSubTopicMap map[string][]string) error {
|
||||
for nodeTopic, cTopics := range pubSubTopicMap {
|
||||
nodeTopic := nodeTopic
|
||||
_, err := wakuNode.Relay().Subscribe(ctx, wprotocol.NewContentFilter(nodeTopic, cTopics...), relay.WithoutConsumer())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(options.Rendezvous.Nodes) != 0 {
|
||||
// Register the node in rendezvous point
|
||||
iter := rendezvous.NewRendezvousPointIterator(options.Rendezvous.Nodes)
|
||||
|
||||
wg.Add(1)
|
||||
go func(nodeTopic string) {
|
||||
t := time.NewTicker(rendezvous.RegisterDefaultTTL)
|
||||
defer t.Stop()
|
||||
defer wg.Done()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-t.C:
|
||||
// Register in rendezvous points periodically
|
||||
wakuNode.Rendezvous().RegisterWithNamespace(ctx, nodeTopic, iter.RendezvousPoints())
|
||||
}
|
||||
}
|
||||
}(nodeTopic)
|
||||
|
||||
wg.Add(1)
|
||||
go func(nodeTopic string) {
|
||||
defer wg.Done()
|
||||
desiredOutDegree := wakuNode.Relay().Params().D
|
||||
t := time.NewTicker(7 * time.Second)
|
||||
defer t.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-t.C:
|
||||
peerCnt := len(wakuNode.Relay().PubSub().ListPeers(nodeTopic))
|
||||
peersToFind := desiredOutDegree - peerCnt
|
||||
if peersToFind <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
rp := <-iter.Next(ctx)
|
||||
if rp == nil {
|
||||
continue
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 7*time.Second)
|
||||
wakuNode.Rendezvous().DiscoverWithNamespace(ctx, nodeTopic, rp, peersToFind)
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}(nodeTopic)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Protected topics
|
||||
for _, protectedTopic := range options.Relay.ProtectedTopics {
|
||||
if err := wakuNode.Relay().AddSignedTopicValidator(protectedTopic.Topic, protectedTopic.PublicKey); err != nil {
|
||||
return nonRecoverErrorMsg("could not add signed topic validator: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
//go:build gowaku_rln
|
||||
// +build gowaku_rln
|
||||
|
||||
package main
|
||||
|
||||
@ -16,12 +16,23 @@ func rlnFlags() []cli.Flag {
|
||||
Usage: "Enable spam protection through rln-relay",
|
||||
Destination: &options.RLNRelay.Enable,
|
||||
},
|
||||
&cli.GenericFlag{
|
||||
Name: "rln-relay-cred-index",
|
||||
Usage: "the index of the onchain commitment to use",
|
||||
Value: &wcli.OptionalUint{
|
||||
Value: &options.RLNRelay.MembershipIndex,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "rln-relay-membership-index",
|
||||
Value: 0,
|
||||
Usage: "(experimental) the index of node in the rln-relay group: a value between 0-99 inclusive",
|
||||
Destination: &options.RLNRelay.MembershipIndex,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "rln-relay-pubsub-topic",
|
||||
Value: "/waku/2/default-waku/proto",
|
||||
Usage: "the pubsub topic for which rln-relay gets enabled",
|
||||
Destination: &options.RLNRelay.PubsubTopic,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "rln-relay-content-topic",
|
||||
Value: "/toy-chat/2/luzhou/proto",
|
||||
Usage: "the content topic for which rln-relay gets enabled",
|
||||
Destination: &options.RLNRelay.ContentTopic,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "rln-relay-dynamic",
|
||||
@ -40,11 +51,14 @@ func rlnFlags() []cli.Flag {
|
||||
Usage: "Password for encrypting RLN credentials",
|
||||
Destination: &options.RLNRelay.CredentialsPassword,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "rln-relay-tree-path",
|
||||
Value: "",
|
||||
Usage: "Path to the RLN merkle tree sled db (https://github.com/spacejam/sled)",
|
||||
Destination: &options.RLNRelay.TreePath,
|
||||
// TODO: this is a good candidate option for subcommands
|
||||
// TODO: consider accepting a private key file and passwd
|
||||
&cli.GenericFlag{
|
||||
Name: "rln-relay-eth-account-private-key",
|
||||
Usage: "Ethereum account private key used for registering in member contract",
|
||||
Value: &wcli.PrivateKeyValue{
|
||||
Value: &options.RLNRelay.ETHPrivateKey,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "rln-relay-eth-client-address",
|
||||
@ -54,7 +68,7 @@ func rlnFlags() []cli.Flag {
|
||||
},
|
||||
&cli.GenericFlag{
|
||||
Name: "rln-relay-eth-contract-address",
|
||||
Usage: "Address of membership contract",
|
||||
Usage: "Address of membership contract ",
|
||||
Value: &wcli.AddressValue{
|
||||
Value: &options.RLNRelay.MembershipContractAddress,
|
||||
},
|
||||
@ -1,19 +0,0 @@
|
||||
//go:build gowaku_no_rln
|
||||
// +build gowaku_no_rln
|
||||
|
||||
package rlngenerate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
cli "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Command generates a key file used to generate the node's peerID, encrypted with an optional password
|
||||
var Command = cli.Command{
|
||||
Name: "generate-rln-credentials",
|
||||
Usage: "Generate credentials for usage with RLN",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
return errors.New("not available. Execute `make RLN=true` to add RLN support to go-waku")
|
||||
},
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
|
||||
package rlngenerate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/waku-org/go-waku/logging"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"github.com/waku-org/go-zerokit-rln/rln"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var options Options
|
||||
var logger = utils.Logger().Named("rln-credentials")
|
||||
|
||||
// Command generates a key file used to generate the node's peerID, encrypted with an optional password
|
||||
var Command = cli.Command{
|
||||
Name: "generate-rln-credentials",
|
||||
Usage: "Generate credentials for usage with RLN",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
if options.ETHPrivateKey == nil {
|
||||
err := errors.New("a private key must be specified")
|
||||
logger.Error("validating option flags", zap.Error(err))
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
err := execute(context.Background())
|
||||
if err != nil {
|
||||
logger.Error("registering RLN credentials", zap.Error(err))
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
func execute(ctx context.Context) error {
|
||||
rlnInstance, err := rln.NewRLN()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
web3Config, err := web3.BuildConfig(ctx, options.ETHClientAddress, options.MembershipContractAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// prepare rln membership key pair
|
||||
logger.Info("generating rln credential")
|
||||
identityCredential, err := rlnInstance.MembershipKeyGen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// register the rln-relay peer to the membership contract
|
||||
membershipIndex, err := register(ctx, web3Config, identityCredential.IDCommitment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: clean private key from memory
|
||||
|
||||
err = persistCredentials(identityCredential, membershipIndex, web3Config.ChainID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if logger.Level() == zap.DebugLevel {
|
||||
logger.Info("registered credentials into the membership contract",
|
||||
logging.HexBytes("IDCommitment", identityCredential.IDCommitment[:]),
|
||||
logging.HexBytes("IDNullifier", identityCredential.IDNullifier[:]),
|
||||
logging.HexBytes("IDSecretHash", identityCredential.IDSecretHash[:]),
|
||||
logging.HexBytes("IDTrapDoor", identityCredential.IDTrapdoor[:]),
|
||||
zap.Uint("index", membershipIndex),
|
||||
)
|
||||
} else {
|
||||
logger.Info("registered credentials into the membership contract", logging.HexBytes("idCommitment", identityCredential.IDCommitment[:]), zap.Uint("index", membershipIndex))
|
||||
}
|
||||
|
||||
web3Config.ETHClient.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func persistCredentials(identityCredential *rln.IdentityCredential, treeIndex rln.MembershipIndex, chainID *big.Int) error {
|
||||
appKeystore, err := keystore.New(options.CredentialsPath, dynamic.RLNAppInfo, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
membershipCredential := keystore.MembershipCredentials{
|
||||
IdentityCredential: identityCredential,
|
||||
TreeIndex: treeIndex,
|
||||
MembershipContractInfo: keystore.NewMembershipContractInfo(chainID, options.MembershipContractAddress),
|
||||
}
|
||||
|
||||
err = appKeystore.AddMembershipCredentials(membershipCredential, options.CredentialsPassword)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist credentials: %w", err)
|
||||
}
|
||||
|
||||
logger.Info("persisted credentials succesfully")
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
|
||||
package rlngenerate
|
||||
|
||||
import (
|
||||
cli "github.com/urfave/cli/v2"
|
||||
wcli "github.com/waku-org/go-waku/waku/cliutils"
|
||||
)
|
||||
|
||||
var flags = []cli.Flag{
|
||||
&cli.PathFlag{
|
||||
Name: "cred-path",
|
||||
Usage: "RLN relay membership credentials file",
|
||||
Value: "./rlnKeystore.json",
|
||||
Destination: &options.CredentialsPath,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "cred-password",
|
||||
Value: "password",
|
||||
Usage: "Password for encrypting RLN credentials",
|
||||
Destination: &options.CredentialsPassword,
|
||||
},
|
||||
&cli.GenericFlag{
|
||||
Name: "eth-account-private-key",
|
||||
Usage: "Ethereum account private key used for registering in member contract",
|
||||
Value: &wcli.PrivateKeyValue{
|
||||
Value: &options.ETHPrivateKey,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "eth-client-address",
|
||||
Usage: "Ethereum testnet client address",
|
||||
Value: "ws://localhost:8545",
|
||||
Destination: &options.ETHClientAddress,
|
||||
},
|
||||
&cli.GenericFlag{
|
||||
Name: "eth-contract-address",
|
||||
Usage: "Address of membership contract",
|
||||
Value: &wcli.AddressValue{
|
||||
Value: &options.MembershipContractAddress,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "eth-nonce",
|
||||
Value: "",
|
||||
Usage: "Set an specific ETH transaction nonce. Leave empty to calculate the nonce automatically",
|
||||
Destination: &options.ETHNonce,
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
Name: "eth-gas-limit",
|
||||
Value: 0,
|
||||
Usage: "Gas limit to set for the transaction execution (0 = estimate)",
|
||||
Destination: &options.ETHGasLimit,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "eth-gas-price",
|
||||
Value: "",
|
||||
Usage: "Gas price in wei to use for the transaction execution (empty = gas price oracle)",
|
||||
Destination: &options.ETHGasPrice,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "eth-gas-fee-cap",
|
||||
Value: "",
|
||||
Usage: "Gas fee cap in wei to use for the 1559 transaction execution (empty = gas price oracle)",
|
||||
Destination: &options.ETHGasFeeCap,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "eth-gas-tip-cap",
|
||||
Value: "",
|
||||
Usage: "Gas priority fee cap in wei to use for the 1559 transaction execution (empty = gas price oracle)",
|
||||
Destination: &options.ETHGasTipCap,
|
||||
},
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package rlngenerate
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// Options are settings used to create RLN credentials.
|
||||
type Options struct {
|
||||
CredentialsPath string
|
||||
CredentialsPassword string
|
||||
ETHPrivateKey *ecdsa.PrivateKey
|
||||
ETHClientAddress string
|
||||
MembershipContractAddress common.Address
|
||||
ETHGasLimit uint64
|
||||
ETHNonce string
|
||||
ETHGasPrice string
|
||||
ETHGasFeeCap string
|
||||
ETHGasTipCap string
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
|
||||
package rlngenerate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/waku-org/go-waku/logging"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||
"github.com/waku-org/go-zerokit-rln/rln"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func getMembershipFee(ctx context.Context, rlnContract web3.RLNContract) (*big.Int, error) {
|
||||
return rlnContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
|
||||
}
|
||||
|
||||
func buildTransactor(ctx context.Context, membershipFee *big.Int, chainID *big.Int) (*bind.TransactOpts, error) {
|
||||
auth, err := bind.NewKeyedTransactorWithChainID(options.ETHPrivateKey, chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auth.Value = membershipFee
|
||||
auth.Context = ctx
|
||||
auth.GasLimit = options.ETHGasLimit
|
||||
|
||||
var ok bool
|
||||
|
||||
if options.ETHNonce != "" {
|
||||
nonce := &big.Int{}
|
||||
auth.Nonce, ok = nonce.SetString(options.ETHNonce, 10)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid nonce value")
|
||||
}
|
||||
}
|
||||
|
||||
if options.ETHGasFeeCap != "" {
|
||||
gasFeeCap := &big.Int{}
|
||||
auth.GasFeeCap, ok = gasFeeCap.SetString(options.ETHGasFeeCap, 10)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid gas fee cap value")
|
||||
}
|
||||
}
|
||||
|
||||
if options.ETHGasTipCap != "" {
|
||||
gasTipCap := &big.Int{}
|
||||
auth.GasTipCap, ok = gasTipCap.SetString(options.ETHGasTipCap, 10)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid gas tip cap value")
|
||||
}
|
||||
}
|
||||
|
||||
if options.ETHGasPrice != "" {
|
||||
gasPrice := &big.Int{}
|
||||
auth.GasPrice, ok = gasPrice.SetString(options.ETHGasPrice, 10)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid gas price value")
|
||||
}
|
||||
}
|
||||
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
func register(ctx context.Context, web3Config *web3.Config, idComm rln.IDCommitment) (rln.MembershipIndex, error) {
|
||||
// check if the contract exists by calling a static function
|
||||
membershipFee, err := getMembershipFee(ctx, web3Config.RLNContract)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
auth, err := buildTransactor(ctx, membershipFee, web3Config.ChainID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
log.Debug("registering an id commitment", zap.Binary("idComm", idComm[:]))
|
||||
|
||||
// registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||
tx, err := web3Config.RegistryContract.Register(auth, web3Config.RLNContract.StorageIndex, rln.Bytes32ToBigInt(idComm))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("transaction error: %w", err)
|
||||
}
|
||||
|
||||
explorerURL := ""
|
||||
switch web3Config.ChainID.Int64() {
|
||||
case 1:
|
||||
explorerURL = "https://etherscan.io"
|
||||
case 5:
|
||||
explorerURL = "https://goerli.etherscan.io"
|
||||
case 11155111:
|
||||
explorerURL = "https://sepolia.etherscan.io"
|
||||
}
|
||||
|
||||
if explorerURL != "" {
|
||||
logger.Info(fmt.Sprintf("transaction broadcasted, find details of your registration transaction in %s/tx/%s", explorerURL, tx.Hash()))
|
||||
} else {
|
||||
logger.Info("transaction broadcasted.", zap.String("transactionHash", tx.Hash().String()))
|
||||
}
|
||||
|
||||
logger.Warn("waiting for transaction to be mined...")
|
||||
|
||||
txReceipt, err := bind.WaitMined(ctx, web3Config.ETHClient, tx)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("transaction error: %w", err)
|
||||
}
|
||||
|
||||
if txReceipt.Status != types.ReceiptStatusSuccessful {
|
||||
return 0, errors.New("transaction reverted")
|
||||
}
|
||||
|
||||
// the receipt topic holds the hash of signature of the raised events
|
||||
evt, err := web3Config.RLNContract.ParseMemberRegistered(*txReceipt.Logs[0])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var eventIDComm rln.IDCommitment = rln.BigIntToBytes32(evt.IdCommitment)
|
||||
|
||||
log.Debug("information extracted from tx log", zap.Uint64("blockNumber", evt.Raw.BlockNumber), logging.HexBytes("idCommitment", eventIDComm[:]), zap.Uint64("index", evt.Index.Uint64()))
|
||||
|
||||
if eventIDComm != idComm {
|
||||
return 0, errors.New("invalid id commitment key")
|
||||
}
|
||||
|
||||
return rln.MembershipIndex(uint(evt.Index.Int64())), nil
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
//go:build gowaku_no_rln
|
||||
// +build gowaku_no_rln
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
)
|
||||
|
||||
func AppendRLNProof(node *node.WakuNode, msg *pb.WakuMessage) error {
|
||||
return nil
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
"github.com/waku-org/go-waku/cmd/waku/server"
|
||||
"github.com/waku-org/go-waku/logging"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||
waku_proto "github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AdminService struct {
|
||||
node *node.WakuNode
|
||||
mux *chi.Mux
|
||||
log *zap.Logger
|
||||
}
|
||||
|
||||
type WakuPeer struct {
|
||||
ID string `json:"id"`
|
||||
MultiAddrs []string `json:"multiaddrs"`
|
||||
Protocols []string `json:"protocols"`
|
||||
Connected bool `json:"connected"`
|
||||
PubsubTopics []string `json:"pubsubTopics"`
|
||||
}
|
||||
|
||||
type WakuPeerInfo struct {
|
||||
MultiAddr string `json:"multiaddr"`
|
||||
Shards []int `json:"shards"`
|
||||
Protocols []string `json:"protocols"`
|
||||
}
|
||||
|
||||
const routeAdminV1Peers = "/admin/v1/peers"
|
||||
|
||||
func NewAdminService(node *node.WakuNode, m *chi.Mux, log *zap.Logger) *AdminService {
|
||||
d := &AdminService{
|
||||
node: node,
|
||||
mux: m,
|
||||
log: log,
|
||||
}
|
||||
|
||||
m.Get(routeAdminV1Peers, d.getV1Peers)
|
||||
m.Post(routeAdminV1Peers, d.postV1Peer)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (a *AdminService) getV1Peers(w http.ResponseWriter, req *http.Request) {
|
||||
peers, err := a.node.Peers()
|
||||
if err != nil {
|
||||
a.log.Error("failed to fetch peers", zap.Error(err))
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
a.log.Info("fetched peers", zap.Int("count", len(peers)))
|
||||
|
||||
response := make([]WakuPeer, 0)
|
||||
for _, peer := range peers {
|
||||
if peer.ID.String() == a.node.Host().ID().String() {
|
||||
//Skip own node id
|
||||
continue
|
||||
}
|
||||
wPeer := WakuPeer{
|
||||
ID: peer.ID.String(),
|
||||
Connected: peer.Connected,
|
||||
}
|
||||
|
||||
for _, addr := range peer.Addrs {
|
||||
wPeer.MultiAddrs = append(wPeer.MultiAddrs, addr.String())
|
||||
}
|
||||
for _, proto := range peer.Protocols {
|
||||
if !server.IsWakuProtocol(proto) {
|
||||
a.log.Debug("skipping protocol as it is a non-waku protocol", logging.HostID("peer", peer.ID), zap.String("protocol", string(proto)))
|
||||
continue
|
||||
}
|
||||
wPeer.Protocols = append(wPeer.Protocols, string(proto))
|
||||
}
|
||||
wPeer.PubsubTopics = peer.PubsubTopics
|
||||
response = append(response, wPeer)
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, nil, response)
|
||||
}
|
||||
|
||||
func (a *AdminService) postV1Peer(w http.ResponseWriter, req *http.Request) {
|
||||
var pInfo WakuPeerInfo
|
||||
var topics []string
|
||||
var protos []protocol.ID
|
||||
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&pInfo); err != nil {
|
||||
a.log.Error("failed to decode request", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
addr, err := ma.NewMultiaddr(pInfo.MultiAddr)
|
||||
if err != nil {
|
||||
a.log.Error("building multiaddr", zap.Error(err))
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
for _, shard := range pInfo.Shards {
|
||||
topic := waku_proto.NewStaticShardingPubsubTopic(a.node.ClusterID(), uint16(shard))
|
||||
topics = append(topics, topic.String())
|
||||
}
|
||||
|
||||
for _, proto := range pInfo.Protocols {
|
||||
protos = append(protos, protocol.ID(proto))
|
||||
}
|
||||
|
||||
id, err := a.node.AddPeer([]multiaddr.Multiaddr{addr}, peerstore.Static, topics, protos...)
|
||||
if err != nil {
|
||||
a.log.Error("failed to add peer", zap.Error(err))
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
a.log.Info("add peer successful", logging.HostID("peerID", id))
|
||||
pi := peer.AddrInfo{ID: id, Addrs: []ma.Multiaddr{addr}}
|
||||
err = a.node.Host().Connect(req.Context(), pi)
|
||||
if err != nil {
|
||||
a.log.Error("failed to connect to peer", logging.HostID("peerID", id), zap.Error(err))
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
writeErrOrResponse(w, nil, nil)
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Waku V2 node REST API
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: VAC Team
|
||||
url: https://forum.vac.dev/
|
||||
|
||||
tags:
|
||||
- name: admin
|
||||
description: Admin REST API for WakuV2 node
|
||||
|
||||
paths:
|
||||
/admin/v1/peers:
|
||||
get:
|
||||
summary: Get connected peers info
|
||||
description: Retrieve information about connected peers.
|
||||
operationId: getPeerInfo
|
||||
tags:
|
||||
- admin
|
||||
responses:
|
||||
'200':
|
||||
description: Information about a Waku v2 node.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/WakuPeer'
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
post:
|
||||
summary: Adds new peer(s) to connect with
|
||||
description: Adds new peer(s) to connect with.
|
||||
operationId: postPeerInfo
|
||||
tags:
|
||||
- admin
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
items:
|
||||
$ref: '#/components/schemas/WakuPeerInfo'
|
||||
responses:
|
||||
'200':
|
||||
description: Ok
|
||||
'400':
|
||||
description: Cannot connect to one or more peers.
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
|
||||
components:
|
||||
schemas:
|
||||
WakuPeerInfo:
|
||||
type: object
|
||||
required:
|
||||
- multiaddr
|
||||
- shards
|
||||
- protocols
|
||||
protocols:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
shards:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
WakuPeer:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- addrs
|
||||
- protocols
|
||||
- connected
|
||||
properties:
|
||||
connected:
|
||||
type: string
|
||||
addrs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
protocols:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
connected:
|
||||
type: boolean
|
||||
pubsubTopics:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
@ -1,380 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/waku-org/go-waku/logging"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/peermanager"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const filterV2Subscriptions = "/filter/v2/subscriptions"
|
||||
const filterv2Messages = "/filter/v2/messages"
|
||||
|
||||
// FilterService represents the REST service for Filter client
|
||||
type FilterService struct {
|
||||
node *node.WakuNode
|
||||
cancel context.CancelFunc
|
||||
|
||||
log *zap.Logger
|
||||
|
||||
cache *filterCache
|
||||
runner *runnerService
|
||||
}
|
||||
|
||||
// Start starts the RelayService
|
||||
func (s *FilterService) Start(ctx context.Context) {
|
||||
|
||||
for _, sub := range s.node.FilterLightnode().Subscriptions() {
|
||||
s.cache.subscribe(sub.ContentFilter)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
s.cancel = cancel
|
||||
s.runner.Start(ctx)
|
||||
}
|
||||
|
||||
// Stop stops the RelayService
|
||||
func (r *FilterService) Stop() {
|
||||
if r.cancel == nil {
|
||||
return
|
||||
}
|
||||
r.cancel()
|
||||
}
|
||||
|
||||
// NewFilterService returns an instance of FilterService
|
||||
func NewFilterService(node *node.WakuNode, m *chi.Mux, cacheCapacity int, log *zap.Logger) *FilterService {
|
||||
logger := log.Named("filter")
|
||||
|
||||
s := &FilterService{
|
||||
node: node,
|
||||
log: logger,
|
||||
cache: newFilterCache(cacheCapacity, logger),
|
||||
}
|
||||
|
||||
m.Route(filterV2Subscriptions, func(r chi.Router) {
|
||||
r.Get("/", s.ping)
|
||||
r.Get("/{requestId}", s.ping)
|
||||
r.Post("/", s.subscribe)
|
||||
r.Delete("/", s.unsubscribe)
|
||||
r.Delete("/all", s.unsubscribeAll)
|
||||
})
|
||||
|
||||
m.Route(filterv2Messages, func(r chi.Router) {
|
||||
r.Get("/{contentTopic}", s.getMessagesByContentTopic)
|
||||
r.Get("/{pubsubTopic}/{contentTopic}", s.getMessagesByPubsubTopic)
|
||||
})
|
||||
|
||||
s.runner = newRunnerService(node.Broadcaster(), s.cache.addMessage)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func convertFilterErrorToHttpStatus(err error) (int, string) {
|
||||
code := http.StatusInternalServerError
|
||||
statusDesc := "ping request failed"
|
||||
|
||||
filterErrorCode := filter.ExtractCodeFromFilterError(err.Error())
|
||||
switch filterErrorCode {
|
||||
case 404:
|
||||
code = http.StatusNotFound
|
||||
statusDesc = "peer has no subscription"
|
||||
case 300:
|
||||
case 400:
|
||||
code = http.StatusBadRequest
|
||||
statusDesc = "bad request format"
|
||||
case 504:
|
||||
code = http.StatusGatewayTimeout
|
||||
case 503:
|
||||
code = http.StatusServiceUnavailable
|
||||
}
|
||||
return code, statusDesc
|
||||
}
|
||||
|
||||
// 400 for bad requestId
|
||||
// 404 when request failed or no suitable peers
|
||||
// 200 when ping successful
|
||||
func (s *FilterService) ping(w http.ResponseWriter, req *http.Request) {
|
||||
requestID := chi.URLParam(req, "requestId")
|
||||
if requestID == "" {
|
||||
writeResponse(w, &filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "bad request id",
|
||||
}, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// selecting random peer that supports filter protocol
|
||||
peerId := s.getRandomFilterPeer(req.Context(), requestID, w)
|
||||
if peerId == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.node.FilterLightnode().Ping(req.Context(), peerId, filter.WithPingRequestId([]byte(requestID))); err != nil {
|
||||
s.log.Error("ping request failed", zap.Error(err))
|
||||
|
||||
code, statusDesc := convertFilterErrorToHttpStatus(err)
|
||||
|
||||
writeResponse(w, &filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: statusDesc,
|
||||
}, code)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// success
|
||||
writeResponse(w, &filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: http.StatusText(http.StatusOK),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
// same for FilterUnsubscribeRequest
|
||||
type filterSubscriptionRequest struct {
|
||||
RequestID string `json:"requestId"`
|
||||
ContentFilters []string `json:"contentFilters"`
|
||||
PubsubTopic string `json:"pubsubTopic"`
|
||||
}
|
||||
|
||||
type filterSubscriptionResponse struct {
|
||||
RequestID string `json:"requestId"`
|
||||
StatusDesc string `json:"statusDesc"`
|
||||
}
|
||||
|
||||
// 400 on invalid request
|
||||
// 404 on failed subscription
|
||||
// 200 on single returned successful subscription
|
||||
// NOTE: subscribe on filter client randomly selects a peer if missing for given pubSubTopic
|
||||
func (s *FilterService) subscribe(w http.ResponseWriter, req *http.Request) {
|
||||
message := filterSubscriptionRequest{}
|
||||
if !s.readBody(w, req, &message) {
|
||||
return
|
||||
}
|
||||
|
||||
contentFilter := protocol.NewContentFilter(message.PubsubTopic, message.ContentFilters...)
|
||||
//
|
||||
subscriptions, err := s.node.FilterLightnode().Subscribe(req.Context(),
|
||||
contentFilter,
|
||||
filter.WithRequestID([]byte(message.RequestID)))
|
||||
|
||||
// on partial subscribe failure
|
||||
if len(subscriptions) > 0 && err != nil {
|
||||
s.log.Error("partial subscribe failed", zap.Error(err))
|
||||
// on partial failure
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: err.Error(),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.log.Error("subscription failed", zap.Error(err))
|
||||
code := filter.ExtractCodeFromFilterError(err.Error())
|
||||
if code == -1 {
|
||||
code = http.StatusBadRequest
|
||||
}
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: "subscription failed",
|
||||
}, code)
|
||||
return
|
||||
}
|
||||
|
||||
// on success
|
||||
s.cache.subscribe(contentFilter)
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: http.StatusText(http.StatusOK),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
// 400 on invalid request
|
||||
// 500 on failed subscription
|
||||
// 200 on successful unsubscribe
|
||||
// NOTE: unsubscribe on filter client will remove subscription from all peers with matching pubSubTopic, if peerId is not provided
|
||||
// to match functionality in nwaku, we will randomly select a peer that supports filter protocol.
|
||||
func (s *FilterService) unsubscribe(w http.ResponseWriter, req *http.Request) {
|
||||
message := filterSubscriptionRequest{} // as pubSubTopics can also be present
|
||||
if !s.readBody(w, req, &message) {
|
||||
return
|
||||
}
|
||||
|
||||
peerId := s.getRandomFilterPeer(req.Context(), message.RequestID, w)
|
||||
if peerId == "" {
|
||||
return
|
||||
}
|
||||
|
||||
contentFilter := protocol.NewContentFilter(message.PubsubTopic, message.ContentFilters...)
|
||||
// unsubscribe on filter
|
||||
result, err := s.node.FilterLightnode().Unsubscribe(
|
||||
req.Context(),
|
||||
contentFilter,
|
||||
filter.WithRequestID([]byte(message.RequestID)),
|
||||
filter.WithPeer(peerId),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
s.log.Error("unsubscribe failed", zap.Error(err))
|
||||
if result == nil {
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: err.Error(),
|
||||
}, http.StatusBadRequest)
|
||||
}
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: err.Error(),
|
||||
}, http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
// on success
|
||||
for cTopic := range contentFilter.ContentTopics {
|
||||
if !s.node.FilterLightnode().IsListening(contentFilter.PubsubTopic, cTopic) {
|
||||
s.cache.unsubscribe(contentFilter.PubsubTopic, cTopic)
|
||||
}
|
||||
}
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: s.unsubscribeGetMessage(result),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func (s *FilterService) unsubscribeGetMessage(result *filter.WakuFilterPushResult) string {
|
||||
if result == nil {
|
||||
return http.StatusText(http.StatusOK)
|
||||
}
|
||||
var peerIds string
|
||||
ind := 0
|
||||
for _, entry := range result.Errors() {
|
||||
if entry.Err != nil {
|
||||
s.log.Error("can't unsubscribe", logging.HostID("peer", entry.PeerID), zap.Error(entry.Err))
|
||||
if ind != 0 {
|
||||
peerIds += ", "
|
||||
}
|
||||
peerIds += entry.PeerID.String()
|
||||
}
|
||||
ind++
|
||||
}
|
||||
if peerIds != "" {
|
||||
return "can't unsubscribe from " + peerIds
|
||||
}
|
||||
return http.StatusText(http.StatusOK)
|
||||
}
|
||||
|
||||
type filterUnsubscribeAllRequest struct {
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
|
||||
func (s *FilterService) readBody(w http.ResponseWriter, req *http.Request, message interface{}) bool {
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(message); err != nil {
|
||||
s.log.Error("bad request", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
defer req.Body.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
// 400 on invalid request
|
||||
// 500 on failed subscription
|
||||
// 200 on all successful unsubscribe
|
||||
// unsubscribe all subscriptions for a given peer
|
||||
func (s *FilterService) unsubscribeAll(w http.ResponseWriter, req *http.Request) {
|
||||
message := filterUnsubscribeAllRequest{}
|
||||
if !s.readBody(w, req, &message) {
|
||||
return
|
||||
}
|
||||
|
||||
peerId := s.getRandomFilterPeer(req.Context(), message.RequestID, w)
|
||||
if peerId == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// unsubscribe all subscriptions for a given peer
|
||||
errCh, err := s.node.FilterLightnode().UnsubscribeAll(
|
||||
req.Context(),
|
||||
filter.WithRequestID([]byte(message.RequestID)),
|
||||
filter.WithPeer(peerId),
|
||||
)
|
||||
if err != nil {
|
||||
s.log.Error("unsubscribeAll failed", zap.Error(err))
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: err.Error(),
|
||||
}, http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
// on success
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: message.RequestID,
|
||||
StatusDesc: s.unsubscribeGetMessage(errCh),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func (s FilterService) getRandomFilterPeer(ctx context.Context, requestId string, w http.ResponseWriter) peer.ID {
|
||||
// selecting random peer that supports filter protocol
|
||||
peerIds, err := s.node.PeerManager().SelectPeers(peermanager.PeerSelectionCriteria{
|
||||
SelectionType: peermanager.Automatic,
|
||||
Proto: filter.FilterSubscribeID_v20beta1,
|
||||
Ctx: ctx,
|
||||
})
|
||||
if err != nil {
|
||||
s.log.Error("selecting peer", zap.Error(err))
|
||||
writeResponse(w, filterSubscriptionResponse{
|
||||
RequestID: requestId,
|
||||
StatusDesc: "No suitable peers",
|
||||
}, http.StatusServiceUnavailable)
|
||||
return ""
|
||||
}
|
||||
return peerIds[0]
|
||||
}
|
||||
|
||||
func (s *FilterService) getMessagesByContentTopic(w http.ResponseWriter, req *http.Request) {
|
||||
contentTopic := topicFromPath(w, req, "contentTopic", s.log)
|
||||
if contentTopic == "" {
|
||||
return
|
||||
}
|
||||
pubsubTopic, err := protocol.GetPubSubTopicFromContentTopic(contentTopic)
|
||||
if err != nil {
|
||||
writeGetMessageErr(w, fmt.Errorf("bad content topic"), http.StatusBadRequest, s.log)
|
||||
return
|
||||
}
|
||||
s.getMessages(w, req, pubsubTopic, contentTopic)
|
||||
}
|
||||
|
||||
func (s *FilterService) getMessagesByPubsubTopic(w http.ResponseWriter, req *http.Request) {
|
||||
contentTopic := topicFromPath(w, req, "contentTopic", s.log)
|
||||
if contentTopic == "" {
|
||||
return
|
||||
}
|
||||
pubsubTopic := topicFromPath(w, req, "pubsubTopic", s.log)
|
||||
if pubsubTopic == "" {
|
||||
return
|
||||
}
|
||||
s.getMessages(w, req, pubsubTopic, contentTopic)
|
||||
}
|
||||
|
||||
// 400 on invalid request
|
||||
// 500 on failed subscription
|
||||
// 200 on all successful unsubscribe
|
||||
// unsubscribe all subscriptions for a given peer
|
||||
func (s *FilterService) getMessages(w http.ResponseWriter, req *http.Request, pubsubTopic, contentTopic string) {
|
||||
msgs, err := s.cache.getMessages(pubsubTopic, contentTopic)
|
||||
if err != nil {
|
||||
writeGetMessageErr(w, err, http.StatusNotFound, s.log)
|
||||
return
|
||||
}
|
||||
writeResponse(w, msgs, http.StatusOK)
|
||||
}
|
||||
@ -1,337 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Waku V2 node REST API
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: VAC Team
|
||||
url: https://forum.vac.dev/
|
||||
tags:
|
||||
- name: filter
|
||||
description: Filter REST API for WakuV2 node
|
||||
|
||||
paths:
|
||||
/filter/v2/subscriptions/{requestId}:
|
||||
get: # get_waku_v2_filter_v2_subscription - ping
|
||||
summary: Subscriber-ping - a peer can query if there is a registered subscription for it
|
||||
description: |
|
||||
Subscriber peer can query its subscription existence on service node.
|
||||
Returns HTTP200 if exists and HTTP404 if not.
|
||||
Client must not fill anything but requestId in the request body.
|
||||
operationId: subscriberPing
|
||||
tags:
|
||||
- filter
|
||||
parameters:
|
||||
- in: path
|
||||
name: requestId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Id of ping request
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
|
||||
|
||||
/filter/v2/subscriptions:
|
||||
post: # post_waku_v2_filter_v2_subscription
|
||||
summary: Subscribe a peer to an array of content topics under a pubsubTopic
|
||||
description: |
|
||||
Subscribe a peer to an array of content topics under a pubsubTopic.
|
||||
|
||||
It is allowed to refresh or add new content topic to an existing subscription.
|
||||
|
||||
Fields pubsubTopic and contentFilters must be filled.
|
||||
operationId: postSubscriptions
|
||||
tags:
|
||||
- filter
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscribeRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
# TODO: Review the possible errors of this endpoint
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
delete: # delete_waku_v2_filter_v2_subscription
|
||||
summary: Unsubscribe a peer from content topics
|
||||
description: |
|
||||
Unsubscribe a peer from content topics
|
||||
Only that subscription will be removed which matches existing.
|
||||
operationId: deleteSubscriptions
|
||||
tags:
|
||||
- filter
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterUnsubscribeRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
|
||||
/filter/v2/subscriptions/all:
|
||||
delete: # delete_waku_v2_filter_v2_subscription
|
||||
summary: Unsubscribe a peer from all content topics
|
||||
description: |
|
||||
Unsubscribe a peer from all content topics
|
||||
operationId: deleteAllSubscriptions
|
||||
tags:
|
||||
- filter
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterUnsubscribeAllRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterSubscriptionResponse'
|
||||
/filter/v2/messages/{contentTopic}:
|
||||
get: # get_waku_v2_filter_v2_messages
|
||||
summary: Get the latest messages on the polled content topic
|
||||
description: Get a list of messages that were received on a subscribed content topic after the last time this method was called.
|
||||
operationId: getMessagesByTopic
|
||||
tags:
|
||||
- filter
|
||||
parameters:
|
||||
- in: path
|
||||
name: contentTopic # Note the name is the same as in the path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Content topic of message
|
||||
responses:
|
||||
'200':
|
||||
description: The latest messages on the polled topic.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterGetMessagesResponse'
|
||||
# TODO: Review the possible errors of this endpoint
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
/filter/v2/messages/{pubsubTopic}/{contentTopic}:
|
||||
get: # get_waku_v2_filter_v2_messages
|
||||
summary: Get the latest messages on the polled pubsub/content topic pair
|
||||
description: Get a list of messages that were received on a subscribed content topic after the last time this method was called.
|
||||
operationId: getMessagesByTopic
|
||||
tags:
|
||||
- filter
|
||||
parameters:
|
||||
- in: path
|
||||
name: contentTopic # Note the name is the same as in the path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Content topic of message
|
||||
- in: path
|
||||
name: pubsubTopic # Note the name is the same as in the path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: pubsub topic of message
|
||||
responses:
|
||||
'200':
|
||||
description: The latest messages on the polled topic.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FilterGetMessagesResponse'
|
||||
# TODO: Review the possible errors of this endpoint
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'5XX':
|
||||
description: Unexpected error.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
components:
|
||||
PubSubTopic:
|
||||
type: string
|
||||
ContentTopic:
|
||||
type: string
|
||||
|
||||
FilterSubscriptionResponse:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
statusDesc:
|
||||
type: string
|
||||
required:
|
||||
- requestId
|
||||
|
||||
FilterSubscribeRequest:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
contentFilters:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ContentTopic'
|
||||
pubsubTopic:
|
||||
$ref: "#/components/schemas/PubSubTopic"
|
||||
required:
|
||||
- requestId
|
||||
- contentFilters
|
||||
- pubsubTopic
|
||||
|
||||
FilterUnsubscribeRequest:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
contentFilters:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ContentTopic'
|
||||
pubsubTopic:
|
||||
$ref: "#/components/schemas/PubSubTopic"
|
||||
required:
|
||||
- requestId
|
||||
- contentFilters
|
||||
|
||||
FilterUnsubscribeAllRequest:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
required:
|
||||
- requestId
|
||||
|
||||
FilterGetMessagesResponse:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FilterWakuMessage'
|
||||
|
||||
FilterWakuMessage:
|
||||
type: object
|
||||
properties:
|
||||
payload:
|
||||
type: string
|
||||
format: byte
|
||||
contentTopic:
|
||||
$ref: '#/components/schemas/ContentTopic'
|
||||
version:
|
||||
type: number
|
||||
timestamp:
|
||||
type: number
|
||||
required:
|
||||
- payload
|
||||
@ -1,84 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type filterCache struct {
|
||||
capacity int
|
||||
mu sync.RWMutex
|
||||
log *zap.Logger
|
||||
data map[string]map[string][]*RestWakuMessage
|
||||
}
|
||||
|
||||
func newFilterCache(capacity int, log *zap.Logger) *filterCache {
|
||||
return &filterCache{
|
||||
capacity: capacity,
|
||||
data: make(map[string]map[string][]*RestWakuMessage),
|
||||
log: log.Named("cache"),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *filterCache) subscribe(contentFilter protocol.ContentFilter) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
pubSubTopicMap, _ := protocol.ContentFilterToPubSubTopicMap(contentFilter)
|
||||
for pubsubTopic, contentTopics := range pubSubTopicMap {
|
||||
if c.data[pubsubTopic] == nil {
|
||||
c.data[pubsubTopic] = make(map[string][]*RestWakuMessage)
|
||||
}
|
||||
for _, topic := range contentTopics {
|
||||
if c.data[pubsubTopic][topic] == nil {
|
||||
c.data[pubsubTopic][topic] = []*RestWakuMessage{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *filterCache) unsubscribe(pubsubTopic string, contentTopic string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
delete(c.data[pubsubTopic], contentTopic)
|
||||
}
|
||||
|
||||
func (c *filterCache) addMessage(envelope *protocol.Envelope) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
pubsubTopic := envelope.PubsubTopic()
|
||||
contentTopic := envelope.Message().ContentTopic
|
||||
if c.data[pubsubTopic] == nil || c.data[pubsubTopic][contentTopic] == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Keep a specific max number of message per topic
|
||||
if len(c.data[pubsubTopic][contentTopic]) >= c.capacity {
|
||||
c.data[pubsubTopic][contentTopic] = c.data[pubsubTopic][contentTopic][1:]
|
||||
}
|
||||
|
||||
message := &RestWakuMessage{}
|
||||
if err := message.FromProto(envelope.Message()); err != nil {
|
||||
c.log.Error("converting protobuffer msg into rest msg", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
c.data[pubsubTopic][contentTopic] = append(c.data[pubsubTopic][contentTopic], message)
|
||||
}
|
||||
|
||||
func (c *filterCache) getMessages(pubsubTopic string, contentTopic string) ([]*RestWakuMessage, error) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
if c.data[pubsubTopic] == nil || c.data[pubsubTopic][contentTopic] == nil {
|
||||
return nil, fmt.Errorf("not subscribed to pubsubTopic:%s contentTopic: %s", pubsubTopic, contentTopic)
|
||||
}
|
||||
msgs := c.data[pubsubTopic][contentTopic]
|
||||
c.data[pubsubTopic][contentTopic] = []*RestWakuMessage{}
|
||||
return msgs, nil
|
||||
}
|
||||
@ -1,393 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/libp2p/go-libp2p/core/peerstore"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/waku-org/go-waku/tests"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
wakupeerstore "github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
func createNode(t *testing.T, opts ...node.WakuNodeOption) *node.WakuNode {
|
||||
node, err := node.New(opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = node.Start(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
// node2 connects to node1
|
||||
func twoFilterConnectedNodes(t *testing.T, pubSubTopics ...string) (*node.WakuNode, *node.WakuNode) {
|
||||
node1 := createNode(t, node.WithWakuFilterFullNode(filter.WithFullNodeRateLimiter(rate.Inf, 0))) // full node filter
|
||||
node2 := createNode(t, node.WithWakuFilterLightNode()) // light node filter
|
||||
|
||||
node2.Host().Peerstore().AddAddr(node1.Host().ID(), tests.GetHostAddress(node1.Host()), peerstore.PermanentAddrTTL)
|
||||
err := node2.Host().Peerstore().AddProtocols(node1.Host().ID(), filter.FilterSubscribeID_v20beta1)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = node2.Host().Peerstore().(*wakupeerstore.WakuPeerstoreImpl).SetPubSubTopics(node1.Host().ID(), pubSubTopics)
|
||||
require.NoError(t, err)
|
||||
|
||||
return node1, node2
|
||||
}
|
||||
|
||||
// test 400, 404 status code for ping rest endpoint
|
||||
// both requests are not successful
|
||||
func TestFilterPingFailure(t *testing.T) {
|
||||
node1, node2 := twoFilterConnectedNodes(t)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
router := chi.NewRouter()
|
||||
_ = NewFilterService(node2, router, 0, utils.Logger())
|
||||
|
||||
// with empty requestID
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("/filter/v2/subscriptions/%s", ""), nil)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: "",
|
||||
StatusDesc: "bad request id",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
|
||||
// no subscription with peer
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("/filter/v2/subscriptions/%s", requestID), nil)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "peer has no subscription",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusNotFound, rr.Code)
|
||||
}
|
||||
|
||||
// create a filter subscription to the peer and try peer that peer
|
||||
// both steps should be successful
|
||||
func TestFilterSubscribeAndPing(t *testing.T) {
|
||||
pubsubTopic := "/waku/2/test/proto"
|
||||
contentTopics := []string{"test"}
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
|
||||
node1, node2 := twoFilterConnectedNodes(t, pubsubTopic)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
router := chi.NewRouter()
|
||||
_ = NewFilterService(node2, router, 0, utils.Logger())
|
||||
|
||||
// create subscription to peer
|
||||
rr := httptest.NewRecorder()
|
||||
reqReader := strings.NewReader(toString(t, filterSubscriptionRequest{
|
||||
RequestID: requestID,
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentFilters: contentTopics,
|
||||
}))
|
||||
req, _ := http.NewRequest(http.MethodPost, filterV2Subscriptions, reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// trying pinging the peer once there is subscription to it
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", filterV2Subscriptions, requestID), nil)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
|
||||
// create subscription to peer
|
||||
// delete the subscription to the peer with matching pubSub and contentTopic
|
||||
func TestFilterSubscribeAndUnsubscribe(t *testing.T) {
|
||||
pubsubTopic := "/waku/2/test/proto"
|
||||
contentTopics := []string{"test"}
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
|
||||
node1, node2 := twoFilterConnectedNodes(t, pubsubTopic)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
router := chi.NewRouter()
|
||||
_ = NewFilterService(node2, router, 0, utils.Logger())
|
||||
|
||||
// create subscription to peer
|
||||
rr := httptest.NewRecorder()
|
||||
reqReader := strings.NewReader(toString(t, filterSubscriptionRequest{
|
||||
RequestID: requestID,
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentFilters: contentTopics,
|
||||
}))
|
||||
req, _ := http.NewRequest(http.MethodPost, filterV2Subscriptions, reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// delete the subscription to the peer with matching pubSub and contentTopic
|
||||
requestID = hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr = httptest.NewRecorder()
|
||||
reqReader = strings.NewReader(toString(t, filterSubscriptionRequest{
|
||||
RequestID: requestID,
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentFilters: contentTopics,
|
||||
}))
|
||||
req, _ = http.NewRequest(http.MethodDelete, filterV2Subscriptions, reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
|
||||
// create 2 subscription from filter client to server
|
||||
// make a unsubscribeAll request
|
||||
// try pinging the peer, if 404 is returned then unsubscribeAll was successful
|
||||
func TestFilterAllUnsubscribe(t *testing.T) {
|
||||
pubsubTopic := "/waku/2/test/proto"
|
||||
contentTopics1 := "ct_1"
|
||||
contentTopics2 := "ct_2"
|
||||
|
||||
node1, node2 := twoFilterConnectedNodes(t, pubsubTopic)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
router := chi.NewRouter()
|
||||
_ = NewFilterService(node2, router, 0, utils.Logger())
|
||||
|
||||
// create 2 different subscription to peer
|
||||
for _, ct := range []string{contentTopics1, contentTopics2} {
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr := httptest.NewRecorder()
|
||||
reqReader := strings.NewReader(toString(t, filterSubscriptionRequest{
|
||||
RequestID: requestID,
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentFilters: []string{ct},
|
||||
}))
|
||||
req, _ := http.NewRequest(http.MethodPost, filterV2Subscriptions, reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
|
||||
// delete all subscription to the peer
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr := httptest.NewRecorder()
|
||||
reqReader := strings.NewReader(toString(t, filterUnsubscribeAllRequest{
|
||||
RequestID: requestID,
|
||||
}))
|
||||
req, _ := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/all", filterV2Subscriptions), reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// check if all subscriptions are deleted to the peer are deleted
|
||||
requestID = hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", filterV2Subscriptions, requestID), nil)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "peer has no subscription",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusNotFound, rr.Code)
|
||||
}
|
||||
|
||||
func checkJSON(t *testing.T, expected, actual interface{}) {
|
||||
require.JSONEq(t, toString(t, expected), toString(t, actual))
|
||||
}
|
||||
func getFilterResponse(t *testing.T, body *bytes.Buffer) filterSubscriptionResponse {
|
||||
resp := filterSubscriptionResponse{}
|
||||
err := json.Unmarshal(body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
return resp
|
||||
}
|
||||
func getMessageResponse(t *testing.T, body *bytes.Buffer) []*pb.WakuMessage {
|
||||
resp := []*pb.WakuMessage{}
|
||||
err := json.Unmarshal(body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
return resp
|
||||
}
|
||||
func toString(t *testing.T, data interface{}) string {
|
||||
bytes, err := json.Marshal(data)
|
||||
require.NoError(t, err)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func TestFilterGetMessages(t *testing.T) {
|
||||
pubsubTopic := "/waku/2/test/proto"
|
||||
contentTopic := "/waku/2/app/1"
|
||||
|
||||
// get nodes add connect them
|
||||
generatedPubsubTopic, err := protocol.GetPubSubTopicFromContentTopic(contentTopic)
|
||||
require.NoError(t, err)
|
||||
node1, node2 := twoFilterConnectedNodes(t, pubsubTopic, generatedPubsubTopic)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
// set router and start filter service
|
||||
router := chi.NewRouter()
|
||||
service := NewFilterService(node2, router, 2, utils.Logger())
|
||||
go service.Start(context.Background())
|
||||
defer service.Stop()
|
||||
|
||||
{ // create subscription so that messages are cached
|
||||
for _, pubsubTopic := range []string{"", pubsubTopic} {
|
||||
requestID := hex.EncodeToString(protocol.GenerateRequestID())
|
||||
rr := httptest.NewRecorder()
|
||||
reqReader := strings.NewReader(toString(t, filterSubscriptionRequest{
|
||||
RequestID: requestID,
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentFilters: []string{contentTopic},
|
||||
}))
|
||||
req, _ := http.NewRequest(http.MethodPost, filterV2Subscriptions, reqReader)
|
||||
router.ServeHTTP(rr, req)
|
||||
checkJSON(t, filterSubscriptionResponse{
|
||||
RequestID: requestID,
|
||||
StatusDesc: "OK",
|
||||
}, getFilterResponse(t, rr.Body))
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// submit messages
|
||||
messageByContentTopic := []*protocol.Envelope{
|
||||
genMessage("", contentTopic),
|
||||
genMessage("", contentTopic),
|
||||
genMessage("", contentTopic),
|
||||
}
|
||||
messageByPubsubTopic := []*protocol.Envelope{
|
||||
genMessage(pubsubTopic, contentTopic),
|
||||
}
|
||||
for _, envelope := range append(messageByContentTopic, messageByPubsubTopic...) {
|
||||
node2.Broadcaster().Submit(envelope)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
{ // with malformed contentTopic
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet,
|
||||
fmt.Sprintf("%s/%s", filterv2Messages, url.QueryEscape("/waku/2/wrongtopic")),
|
||||
nil,
|
||||
)
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
require.Equal(t, "bad content topic", rr.Body.String())
|
||||
}
|
||||
|
||||
{ // with check if the cache is working properly
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet,
|
||||
fmt.Sprintf("%s/%s", filterv2Messages, url.QueryEscape(contentTopic)),
|
||||
nil,
|
||||
)
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
checkJSON(t, toMessage(messageByContentTopic[1:]), getMessageResponse(t, rr.Body))
|
||||
}
|
||||
|
||||
{ // check if pubsubTopic is present in the url
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet,
|
||||
fmt.Sprintf("%s//%s", filterv2Messages, url.QueryEscape(contentTopic)),
|
||||
nil,
|
||||
)
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
require.Equal(t, "missing pubsubTopic", rr.Body.String())
|
||||
}
|
||||
|
||||
{ // check messages by pubsub/contentTopic pair
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet,
|
||||
fmt.Sprintf("%s/%s/%s", filterv2Messages, url.QueryEscape(pubsubTopic), url.QueryEscape(contentTopic)),
|
||||
nil,
|
||||
)
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
checkJSON(t, toMessage(messageByPubsubTopic), getMessageResponse(t, rr.Body))
|
||||
}
|
||||
|
||||
{ // check if pubsubTopic/contentTOpic is subscribed or not.
|
||||
rr := httptest.NewRecorder()
|
||||
notSubscibredPubsubTopic := "/waku/2/test2/proto"
|
||||
req, _ := http.NewRequest(http.MethodGet,
|
||||
fmt.Sprintf("%s/%s/%s", filterv2Messages, url.QueryEscape(notSubscibredPubsubTopic), url.QueryEscape(contentTopic)),
|
||||
nil,
|
||||
)
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusNotFound, rr.Code)
|
||||
require.Equal(t,
|
||||
fmt.Sprintf("not subscribed to pubsubTopic:%s contentTopic: %s", notSubscibredPubsubTopic, contentTopic),
|
||||
rr.Body.String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func toMessage(envs []*protocol.Envelope) []*pb.WakuMessage {
|
||||
msgs := make([]*pb.WakuMessage, len(envs))
|
||||
for i, env := range envs {
|
||||
msgs[i] = env.Message()
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func genMessage(pubsubTopic, contentTopic string) *protocol.Envelope {
|
||||
if pubsubTopic == "" {
|
||||
pubsubTopic, _ = protocol.GetPubSubTopicFromContentTopic(contentTopic)
|
||||
}
|
||||
return protocol.NewEnvelope(
|
||||
&pb.WakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: contentTopic,
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
},
|
||||
0,
|
||||
pubsubTopic,
|
||||
)
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
)
|
||||
|
||||
type HealthService struct {
|
||||
node *node.WakuNode
|
||||
mux *chi.Mux
|
||||
}
|
||||
|
||||
const routeHealth = "/health"
|
||||
|
||||
func NewHealthService(node *node.WakuNode, m *chi.Mux) *HealthService {
|
||||
h := &HealthService{
|
||||
node: node,
|
||||
mux: m,
|
||||
}
|
||||
|
||||
m.Get(routeHealth, h.getHealth)
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
type HealthResponse string
|
||||
|
||||
func (d *HealthService) getHealth(w http.ResponseWriter, r *http.Request) {
|
||||
if d.node.RLNRelay() != nil {
|
||||
isReady, err := d.node.RLNRelay().IsReady(r.Context())
|
||||
if err != nil {
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
writeResponse(w, HealthResponse("Health check timed out"), http.StatusInternalServerError)
|
||||
} else {
|
||||
writeResponse(w, HealthResponse(err.Error()), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if isReady {
|
||||
writeResponse(w, HealthResponse("Node is healthy"), http.StatusOK)
|
||||
} else {
|
||||
writeResponse(w, HealthResponse("Node is not ready"), http.StatusInternalServerError)
|
||||
}
|
||||
} else {
|
||||
writeResponse(w, HealthResponse("Non RLN healthcheck is not implemented"), http.StatusNotImplemented)
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Waku V2 node Health REST API
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: VAC Team
|
||||
url: https://forum.vac.dev/
|
||||
|
||||
tags:
|
||||
- name: health
|
||||
description: Healt check REST API for WakuV2 node
|
||||
|
||||
paths:
|
||||
/health:
|
||||
get:
|
||||
summary: Get node health status
|
||||
description: Retrieve readiness of a Waku v2 node.
|
||||
operationId: healthcheck
|
||||
tags:
|
||||
- health
|
||||
responses:
|
||||
'200':
|
||||
description: Waku v2 node is up and running.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
example: Node is healty
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'503':
|
||||
description: Node not initialized or having issues
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
example: Node is not initialized
|
||||
@ -1,212 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_store"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_store/pb"
|
||||
)
|
||||
|
||||
type LegacyStoreService struct {
|
||||
node *node.WakuNode
|
||||
mux *chi.Mux
|
||||
}
|
||||
|
||||
type LegacyStoreResponse struct {
|
||||
Messages []LegacyStoreWakuMessage `json:"messages"`
|
||||
Cursor *LegacyHistoryCursor `json:"cursor,omitempty"`
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
}
|
||||
|
||||
type LegacyHistoryCursor struct {
|
||||
PubsubTopic string `json:"pubsubTopic"`
|
||||
SenderTime string `json:"senderTime"`
|
||||
StoreTime string `json:"storeTime"`
|
||||
Digest []byte `json:"digest"`
|
||||
}
|
||||
|
||||
type LegacyStoreWakuMessage struct {
|
||||
Payload []byte `json:"payload"`
|
||||
ContentTopic string `json:"contentTopic"`
|
||||
Version *uint32 `json:"version,omitempty"`
|
||||
Timestamp *int64 `json:"timestamp,omitempty"`
|
||||
Meta []byte `json:"meta,omitempty"`
|
||||
}
|
||||
|
||||
const routeLegacyStoreMessagesV1 = "/store/v1/messages"
|
||||
|
||||
func NewLegacyStoreService(node *node.WakuNode, m *chi.Mux) *LegacyStoreService {
|
||||
s := &LegacyStoreService{
|
||||
node: node,
|
||||
mux: m,
|
||||
}
|
||||
|
||||
m.Get(routeLegacyStoreMessagesV1, s.getV1Messages)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func getLegacyStoreParams(r *http.Request) (*legacy_store.Query, []legacy_store.HistoryRequestOption, error) {
|
||||
query := &legacy_store.Query{}
|
||||
var options []legacy_store.HistoryRequestOption
|
||||
var err error
|
||||
peerAddrStr := r.URL.Query().Get("peerAddr")
|
||||
var m multiaddr.Multiaddr
|
||||
if peerAddrStr != "" {
|
||||
m, err = multiaddr.NewMultiaddr(peerAddrStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
options = append(options, legacy_store.WithPeerAddr(m))
|
||||
} else {
|
||||
// The user didn't specify a peer address and self-node is configured as a store node.
|
||||
// In this case we assume that the user is willing to retrieve the messages stored by
|
||||
// the local/self store node.
|
||||
options = append(options, legacy_store.WithLocalQuery())
|
||||
}
|
||||
|
||||
query.PubsubTopic = r.URL.Query().Get("pubsubTopic")
|
||||
|
||||
contentTopics := r.URL.Query().Get("contentTopics")
|
||||
if contentTopics != "" {
|
||||
query.ContentTopics = strings.Split(contentTopics, ",")
|
||||
}
|
||||
|
||||
startTimeStr := r.URL.Query().Get("startTime")
|
||||
if startTimeStr != "" {
|
||||
startTime, err := strconv.ParseInt(startTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
query.StartTime = &startTime
|
||||
}
|
||||
|
||||
endTimeStr := r.URL.Query().Get("endTime")
|
||||
if endTimeStr != "" {
|
||||
endTime, err := strconv.ParseInt(endTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
query.EndTime = &endTime
|
||||
}
|
||||
|
||||
var cursor *pb.Index
|
||||
|
||||
senderTimeStr := r.URL.Query().Get("senderTime")
|
||||
storeTimeStr := r.URL.Query().Get("storeTime")
|
||||
digestStr := r.URL.Query().Get("digest")
|
||||
|
||||
if senderTimeStr != "" || storeTimeStr != "" || digestStr != "" {
|
||||
cursor = &pb.Index{}
|
||||
|
||||
if senderTimeStr != "" {
|
||||
cursor.SenderTime, err = strconv.ParseInt(senderTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if storeTimeStr != "" {
|
||||
cursor.ReceiverTime, err = strconv.ParseInt(storeTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if digestStr != "" {
|
||||
cursor.Digest, err = base64.URLEncoding.DecodeString(digestStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cursor.PubsubTopic = query.PubsubTopic
|
||||
|
||||
options = append(options, legacy_store.WithCursor(cursor))
|
||||
}
|
||||
|
||||
pageSizeStr := r.URL.Query().Get("pageSize")
|
||||
ascendingStr := r.URL.Query().Get("ascending")
|
||||
if ascendingStr != "" || pageSizeStr != "" {
|
||||
ascending := true
|
||||
pageSize := uint64(legacy_store.DefaultPageSize)
|
||||
if ascendingStr != "" {
|
||||
ascending, err = strconv.ParseBool(ascendingStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if pageSizeStr != "" {
|
||||
pageSize, err = strconv.ParseUint(pageSizeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if pageSize > legacy_store.MaxPageSize {
|
||||
pageSize = legacy_store.MaxPageSize
|
||||
}
|
||||
}
|
||||
|
||||
options = append(options, legacy_store.WithPaging(ascending, pageSize))
|
||||
}
|
||||
|
||||
return query, options, nil
|
||||
}
|
||||
|
||||
func writeLegacyStoreError(w http.ResponseWriter, code int, err error) {
|
||||
writeResponse(w, LegacyStoreResponse{ErrorMessage: err.Error()}, code)
|
||||
}
|
||||
|
||||
func toLegacyStoreResponse(result *legacy_store.Result) LegacyStoreResponse {
|
||||
response := LegacyStoreResponse{}
|
||||
|
||||
cursor := result.Cursor()
|
||||
if cursor != nil {
|
||||
response.Cursor = &LegacyHistoryCursor{
|
||||
PubsubTopic: cursor.PubsubTopic,
|
||||
SenderTime: fmt.Sprintf("%d", cursor.SenderTime),
|
||||
StoreTime: fmt.Sprintf("%d", cursor.ReceiverTime),
|
||||
Digest: cursor.Digest,
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range result.Messages {
|
||||
response.Messages = append(response.Messages, LegacyStoreWakuMessage{
|
||||
Payload: m.Payload,
|
||||
ContentTopic: m.ContentTopic,
|
||||
Version: m.Version,
|
||||
Timestamp: m.Timestamp,
|
||||
Meta: m.Meta,
|
||||
})
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func (d *LegacyStoreService) getV1Messages(w http.ResponseWriter, r *http.Request) {
|
||||
query, options, err := getLegacyStoreParams(r)
|
||||
if err != nil {
|
||||
writeLegacyStoreError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result, err := d.node.LegacyStore().Query(ctx, *query, options...)
|
||||
if err != nil {
|
||||
writeLegacyStoreError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, nil, toLegacyStoreResponse(result))
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Waku V2 node REST API
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: VAC Team
|
||||
url: https://forum.vac.dev/
|
||||
|
||||
tags:
|
||||
- name: lightpush
|
||||
description: Lightpush REST API for WakuV2 node
|
||||
|
||||
paths:
|
||||
/lightpush/v1/message:
|
||||
post:
|
||||
summary: Request a message relay from a LightPush service provider
|
||||
description: Push a message to be relayed on a PubSub topic.
|
||||
operationId: postMessagesToPubsubTopic
|
||||
tags:
|
||||
- lightpush
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PushRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
'503':
|
||||
description: Service not available
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
components:
|
||||
schemas:
|
||||
PubsubTopic:
|
||||
type: string
|
||||
|
||||
ContentTopic:
|
||||
type: string
|
||||
|
||||
WakuMessage:
|
||||
type: object
|
||||
properties:
|
||||
payload:
|
||||
type: string
|
||||
format: byte
|
||||
contentTopic:
|
||||
$ref: '#/components/schemas/ContentTopic'
|
||||
version:
|
||||
type: number
|
||||
timestamp:
|
||||
type: number
|
||||
required:
|
||||
- payload
|
||||
- contentTopic
|
||||
|
||||
PushRequest:
|
||||
type: object
|
||||
properties:
|
||||
pusbsubTopic:
|
||||
$ref: '#/components/schemas/PubsubTopic'
|
||||
message:
|
||||
$ref: '#/components/schemas/WakuMessage'
|
||||
required:
|
||||
- message
|
||||
@ -1,96 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const routeLightPushV1Messages = "/lightpush/v1/message"
|
||||
|
||||
type LightpushService struct {
|
||||
node *node.WakuNode
|
||||
log *zap.Logger
|
||||
}
|
||||
|
||||
func NewLightpushService(node *node.WakuNode, m *chi.Mux, log *zap.Logger) *LightpushService {
|
||||
serv := &LightpushService{
|
||||
node: node,
|
||||
log: log.Named("lightpush"),
|
||||
}
|
||||
|
||||
m.Post(routeLightPushV1Messages, serv.postMessagev1)
|
||||
|
||||
return serv
|
||||
}
|
||||
|
||||
func (msg lightpushRequest) Check() error {
|
||||
if msg.Message == nil {
|
||||
return errors.New("waku message is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type lightpushRequest struct {
|
||||
PubSubTopic string `json:"pubsubTopic"`
|
||||
Message *RestWakuMessage `json:"message"`
|
||||
}
|
||||
|
||||
// handled error codes are 200, 400, 500, 503
|
||||
func (serv *LightpushService) postMessagev1(w http.ResponseWriter, req *http.Request) {
|
||||
request := &lightpushRequest{}
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(request); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
if err := request.Check(); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
serv.log.Error("writing response", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if serv.node.Lightpush() == nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
message, err := request.Message.ToProto()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
if err != nil {
|
||||
serv.log.Error("writing response", zap.Error(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err = message.Validate(); err != nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
if err != nil {
|
||||
serv.log.Error("writing response", zap.Error(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
_, err = serv.node.Lightpush().Publish(req.Context(), message, lightpush.WithPubSubTopic(request.PubSubTopic))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
if err != nil {
|
||||
serv.log.Error("writing response", zap.Error(err))
|
||||
}
|
||||
} else {
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/libp2p/go-libp2p/core/peerstore"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/waku-org/go-waku/tests"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
wakupeerstore "github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
)
|
||||
|
||||
// node2 connects to node1
|
||||
func twoLightPushConnectedNodes(t *testing.T, pubSubTopic string) (*node.WakuNode, *node.WakuNode) {
|
||||
node1 := createNode(t, node.WithLightPush(), node.WithWakuRelay())
|
||||
node2 := createNode(t, node.WithLightPush(), node.WithWakuRelay())
|
||||
|
||||
_, err := node1.Relay().Subscribe(context.Background(), protocol.NewContentFilter(pubSubTopic))
|
||||
require.NoError(t, err)
|
||||
_, err = node2.Relay().Subscribe(context.Background(), protocol.NewContentFilter(pubSubTopic))
|
||||
require.NoError(t, err)
|
||||
|
||||
node2.Host().Peerstore().AddAddr(node1.Host().ID(), tests.GetHostAddress(node1.Host()), peerstore.PermanentAddrTTL)
|
||||
err = node2.Host().Peerstore().AddProtocols(node1.Host().ID(), lightpush.LightPushID_v20beta1)
|
||||
require.NoError(t, err)
|
||||
err = node2.Host().Peerstore().(*wakupeerstore.WakuPeerstoreImpl).SetPubSubTopics(node1.Host().ID(), []string{pubSubTopic})
|
||||
require.NoError(t, err)
|
||||
return node1, node2
|
||||
}
|
||||
|
||||
func TestLightpushMessagev1(t *testing.T) {
|
||||
pubSubTopic := "/waku/2/default-waku/proto"
|
||||
node1, node2 := twoLightPushConnectedNodes(t, pubSubTopic)
|
||||
defer func() {
|
||||
node1.Stop()
|
||||
node2.Stop()
|
||||
}()
|
||||
|
||||
router := chi.NewRouter()
|
||||
serv := NewLightpushService(node2, router, utils.Logger())
|
||||
_ = serv
|
||||
|
||||
msg := lightpushRequest{
|
||||
PubSubTopic: pubSubTopic,
|
||||
Message: &RestWakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: "abc",
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
},
|
||||
}
|
||||
msgJSONBytes, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeLightPushV1Messages, bytes.NewReader(msgJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/waku-org/go-waku/cmd/waku/server"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
)
|
||||
|
||||
type RestWakuMessage struct {
|
||||
Payload server.Base64URLByte `json:"payload"`
|
||||
ContentTopic string `json:"contentTopic"`
|
||||
Version *uint32 `json:"version,omitempty"`
|
||||
Timestamp *int64 `json:"timestamp,omitempty"`
|
||||
Meta []byte `json:"meta,omitempty"`
|
||||
Ephemeral *bool `json:"ephemeral"`
|
||||
}
|
||||
|
||||
func (r *RestWakuMessage) FromProto(input *pb.WakuMessage) error {
|
||||
if err := input.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Payload = input.Payload
|
||||
r.ContentTopic = input.ContentTopic
|
||||
r.Timestamp = input.Timestamp
|
||||
r.Version = input.Version
|
||||
r.Meta = input.Meta
|
||||
r.Ephemeral = input.Ephemeral
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RestWakuMessage) ToProto() (*pb.WakuMessage, error) {
|
||||
if r == nil {
|
||||
return nil, errors.New("wakumessage is missing")
|
||||
}
|
||||
|
||||
msg := &pb.WakuMessage{
|
||||
Payload: r.Payload,
|
||||
ContentTopic: r.ContentTopic,
|
||||
Version: r.Version,
|
||||
Timestamp: r.Timestamp,
|
||||
Meta: r.Meta,
|
||||
Ephemeral: r.Ephemeral,
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
@ -1,316 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/waku-org/go-waku/cmd/waku/server"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const routeRelayV1Subscriptions = "/relay/v1/subscriptions"
|
||||
const routeRelayV1Messages = "/relay/v1/messages/{topic}"
|
||||
|
||||
const routeRelayV1AutoSubscriptions = "/relay/v1/auto/subscriptions"
|
||||
const routeRelayV1AutoMessages = "/relay/v1/auto/messages"
|
||||
|
||||
// RelayService represents the REST service for WakuRelay
|
||||
type RelayService struct {
|
||||
node *node.WakuNode
|
||||
|
||||
log *zap.Logger
|
||||
|
||||
cacheCapacity uint
|
||||
}
|
||||
|
||||
// NewRelayService returns an instance of RelayService
|
||||
func NewRelayService(node *node.WakuNode, m *chi.Mux, cacheCapacity uint, log *zap.Logger) *RelayService {
|
||||
s := &RelayService{
|
||||
node: node,
|
||||
log: log.Named("relay"),
|
||||
cacheCapacity: cacheCapacity,
|
||||
}
|
||||
|
||||
m.Post(routeRelayV1Subscriptions, s.postV1Subscriptions)
|
||||
m.Delete(routeRelayV1Subscriptions, s.deleteV1Subscriptions)
|
||||
m.Get(routeRelayV1Messages, s.getV1Messages)
|
||||
m.Post(routeRelayV1Messages, s.postV1Message)
|
||||
|
||||
m.Post(routeRelayV1AutoSubscriptions, s.postV1AutoSubscriptions)
|
||||
m.Delete(routeRelayV1AutoSubscriptions, s.deleteV1AutoSubscriptions)
|
||||
|
||||
m.Route(routeRelayV1AutoMessages, func(r chi.Router) {
|
||||
r.Get("/{contentTopic}", s.getV1AutoMessages)
|
||||
r.Post("/", s.postV1AutoMessage)
|
||||
})
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *RelayService) deleteV1Subscriptions(w http.ResponseWriter, req *http.Request) {
|
||||
var topics []string
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&topics); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
var err error
|
||||
for _, topic := range topics {
|
||||
err = r.node.Relay().Unsubscribe(req.Context(), protocol.NewContentFilter(topic))
|
||||
if err != nil {
|
||||
r.log.Error("unsubscribing from topic", zap.String("topic", strings.Replace(strings.Replace(topic, "\n", "", -1), "\r", "", -1)), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
|
||||
func (r *RelayService) postV1Subscriptions(w http.ResponseWriter, req *http.Request) {
|
||||
var topics []string
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&topics); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
var err error
|
||||
var successCnt int
|
||||
var topicToSubscribe string
|
||||
for _, topic := range topics {
|
||||
if topic == "" {
|
||||
topicToSubscribe = relay.DefaultWakuTopic
|
||||
} else {
|
||||
topicToSubscribe = topic
|
||||
}
|
||||
_, err = r.node.Relay().Subscribe(r.node.Relay().Context(), protocol.NewContentFilter(topicToSubscribe), relay.WithCacheSize(r.cacheCapacity))
|
||||
|
||||
if err != nil {
|
||||
r.log.Error("subscribing to topic", zap.String("topic", strings.Replace(topicToSubscribe, "\n", "", -1)), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
successCnt++
|
||||
}
|
||||
|
||||
// on partial subscribe failure
|
||||
if successCnt > 0 && err != nil {
|
||||
r.log.Error("partial subscribe failed", zap.Error(err))
|
||||
// on partial failure
|
||||
writeResponse(w, err, http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
|
||||
func (r *RelayService) getV1Messages(w http.ResponseWriter, req *http.Request) {
|
||||
topic := topicFromPath(w, req, "topic", r.log)
|
||||
if topic == "" {
|
||||
r.log.Debug("topic is not specified, using default waku topic")
|
||||
topic = relay.DefaultWakuTopic
|
||||
}
|
||||
//TODO: Update the API to also take a contentTopic since relay now supports filtering based on contentTopic as well.
|
||||
sub, err := r.node.Relay().GetSubscriptionWithPubsubTopic(topic, "")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
r.log.Error("writing response", zap.Error(err))
|
||||
return
|
||||
}
|
||||
var response []*RestWakuMessage
|
||||
done := false
|
||||
for {
|
||||
if done || len(response) > int(r.cacheCapacity) {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case envelope, open := <-sub.Ch:
|
||||
if !open {
|
||||
r.log.Error("consume channel is closed for subscription", zap.String("pubsubTopic", topic))
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, err = w.Write([]byte("consume channel is closed for subscription"))
|
||||
if err != nil {
|
||||
r.log.Error("writing response", zap.Error(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
message := &RestWakuMessage{}
|
||||
if err := message.FromProto(envelope.Message()); err != nil {
|
||||
r.log.Error("converting protobuffer msg into rest msg", zap.Error(err))
|
||||
} else {
|
||||
response = append(response, message)
|
||||
}
|
||||
case <-req.Context().Done():
|
||||
done = true
|
||||
default:
|
||||
done = true
|
||||
}
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, nil, response)
|
||||
}
|
||||
|
||||
func (r *RelayService) postV1Message(w http.ResponseWriter, req *http.Request) {
|
||||
topic := topicFromPath(w, req, "topic", r.log)
|
||||
if topic == "" {
|
||||
r.log.Debug("topic is not specified, using default waku topic")
|
||||
topic = relay.DefaultWakuTopic
|
||||
}
|
||||
|
||||
var restMessage *RestWakuMessage
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&restMessage); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
message, err := restMessage.ToProto()
|
||||
if err != nil {
|
||||
r.log.Error("failed to convert message to proto", zap.Error(err))
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := server.AppendRLNProof(r.node, message); err != nil {
|
||||
r.log.Error("failed to append RLN proof for the message", zap.Error(err))
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = r.node.Relay().Publish(req.Context(), message, relay.WithPubSubTopic(strings.Replace(topic, "\n", "", -1)))
|
||||
if err != nil {
|
||||
r.log.Error("publishing message", zap.Error(err))
|
||||
if err == pb.ErrMissingPayload || err == pb.ErrMissingContentTopic || err == pb.ErrInvalidMetaLength {
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
|
||||
func (r *RelayService) deleteV1AutoSubscriptions(w http.ResponseWriter, req *http.Request) {
|
||||
var cTopics []string
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&cTopics); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
err := r.node.Relay().Unsubscribe(req.Context(), protocol.NewContentFilter("", cTopics...))
|
||||
if err != nil {
|
||||
r.log.Error("unsubscribing from topics", zap.Strings("contentTopics", cTopics), zap.Error(err))
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
|
||||
func (r *RelayService) postV1AutoSubscriptions(w http.ResponseWriter, req *http.Request) {
|
||||
var cTopics []string
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&cTopics); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
var err error
|
||||
_, err = r.node.Relay().Subscribe(r.node.Relay().Context(), protocol.NewContentFilter("", cTopics...), relay.WithCacheSize(r.cacheCapacity))
|
||||
if err != nil {
|
||||
r.log.Error("subscribing to topics", zap.Strings("contentTopics", cTopics), zap.Error(err))
|
||||
}
|
||||
r.log.Debug("subscribed to topics", zap.Strings("contentTopics", cTopics))
|
||||
|
||||
if err != nil {
|
||||
r.log.Error("writing response", zap.Error(err))
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
} else {
|
||||
writeErrOrResponse(w, err, true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (r *RelayService) getV1AutoMessages(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
cTopic := topicFromPath(w, req, "contentTopic", r.log)
|
||||
sub, err := r.node.Relay().GetSubscription(cTopic)
|
||||
if err != nil {
|
||||
r.log.Error("writing response", zap.Error(err))
|
||||
writeErrResponse(w, r.log, err, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
var response []*RestWakuMessage
|
||||
done := false
|
||||
for {
|
||||
if done || len(response) > int(r.cacheCapacity) {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case envelope := <-sub.Ch:
|
||||
message := &RestWakuMessage{}
|
||||
if err := message.FromProto(envelope.Message()); err != nil {
|
||||
r.log.Error("converting protobuffer msg into rest msg", zap.Error(err))
|
||||
} else {
|
||||
response = append(response, message)
|
||||
}
|
||||
case <-req.Context().Done():
|
||||
done = true
|
||||
default:
|
||||
done = true
|
||||
}
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, nil, response)
|
||||
}
|
||||
|
||||
func (r *RelayService) postV1AutoMessage(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
var restMessage *RestWakuMessage
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
if err := decoder.Decode(&restMessage); err != nil {
|
||||
r.log.Error("decoding request failure", zap.Error(err))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
message, err := restMessage.ToProto()
|
||||
if err != nil {
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if err = server.AppendRLNProof(r.node, message); err != nil {
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = r.node.Relay().Publish(req.Context(), message)
|
||||
if err != nil {
|
||||
r.log.Error("publishing message", zap.Error(err))
|
||||
if err == pb.ErrMissingPayload || err == pb.ErrMissingContentTopic || err == pb.ErrInvalidMetaLength {
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
writeErrResponse(w, r.log, err, http.StatusBadRequest)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,303 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/waku-org/go-waku/tests"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func makeRelayService(t *testing.T, mux *chi.Mux) *RelayService {
|
||||
options := node.WithWakuRelayAndMinPeers(0)
|
||||
n, err := node.New(options)
|
||||
require.NoError(t, err)
|
||||
err = n.Start(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
return NewRelayService(n, mux, 3, utils.Logger())
|
||||
}
|
||||
|
||||
func TestPostV1Message(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
testTopic := "test"
|
||||
|
||||
r := makeRelayService(t, router)
|
||||
msg := &RestWakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: "abc",
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
msgJSONBytes, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.node.Relay().Subscribe(context.Background(), protocol.NewContentFilter(testTopic))
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, "/relay/v1/messages/"+testTopic, bytes.NewReader(msgJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
}
|
||||
|
||||
func TestRelaySubscription(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
|
||||
r := makeRelayService(t, router)
|
||||
|
||||
// Wait for node to start
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
topics := []string{"test"}
|
||||
topicsJSONBytes, err := json.Marshal(topics)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeRelayV1Subscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
|
||||
// Test max messages in subscription
|
||||
now := *utils.GetUnixEpoch()
|
||||
_, err = r.node.Relay().Publish(context.Background(),
|
||||
tests.CreateWakuMessage("test", proto.Int64(now+1)), relay.WithPubSubTopic("test"))
|
||||
require.NoError(t, err)
|
||||
_, err = r.node.Relay().Publish(context.Background(),
|
||||
tests.CreateWakuMessage("test", proto.Int64(now+2)), relay.WithPubSubTopic("test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.node.Relay().Publish(context.Background(),
|
||||
tests.CreateWakuMessage("test", proto.Int64(now+3)), relay.WithPubSubTopic("test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for the messages to be processed
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
// Test deletion
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodDelete, routeRelayV1Subscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
}
|
||||
|
||||
func TestRelayGetV1Messages(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
router1 := chi.NewRouter()
|
||||
|
||||
serviceA := makeRelayService(t, router)
|
||||
|
||||
serviceB := makeRelayService(t, router1)
|
||||
|
||||
hostInfo, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", serviceB.node.Host().ID().String()))
|
||||
require.NoError(t, err)
|
||||
|
||||
var addr multiaddr.Multiaddr
|
||||
for _, a := range serviceB.node.Host().Addrs() {
|
||||
addr = a.Encapsulate(hostInfo)
|
||||
break
|
||||
}
|
||||
err = serviceA.node.DialPeerWithMultiAddress(context.Background(), addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for the dial to complete
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
topics := []string{"test"}
|
||||
topicsJSONBytes, err := json.Marshal(topics)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeRelayV1Subscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// Wait for the subscription to be started
|
||||
time.Sleep(1 * time.Second)
|
||||
ephemeral := true
|
||||
msg := &RestWakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: "test",
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
Ephemeral: &ephemeral,
|
||||
}
|
||||
msgJsonBytes, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodPost, "/relay/v1/messages/test", bytes.NewReader(msgJsonBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// Wait for the message to be received
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, "/relay/v1/messages/test", bytes.NewReader([]byte{}))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
var messages []*pb.WakuMessage
|
||||
err = json.Unmarshal(rr.Body.Bytes(), &messages)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, messages, 1)
|
||||
require.Equal(t, *messages[0].Ephemeral, true)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, "/relay/v1/messages/test", bytes.NewReader([]byte{}))
|
||||
router1.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
}
|
||||
|
||||
func TestPostAutoV1Message(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
|
||||
_ = makeRelayService(t, router)
|
||||
msg := &RestWakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: "/toychat/1/huilong/proto",
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
msgJSONBytes, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeRelayV1AutoMessages, bytes.NewReader(msgJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
|
||||
func TestRelayAutoSubUnsub(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
|
||||
r := makeRelayService(t, router)
|
||||
|
||||
// Wait for node to start
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
cTopic1 := "/toychat/1/huilong/proto"
|
||||
|
||||
cTopics := []string{cTopic1}
|
||||
topicsJSONBytes, err := json.Marshal(cTopics)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeRelayV1AutoSubscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
|
||||
// Test publishing messages after subscription
|
||||
now := *utils.GetUnixEpoch()
|
||||
_, err = r.node.Relay().Publish(context.Background(),
|
||||
tests.CreateWakuMessage(cTopic1, proto.Int64(now+1)))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for the messages to be processed
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
// Test deletion
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodDelete, routeRelayV1AutoSubscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
|
||||
cTopics = append(cTopics, "test")
|
||||
topicsJSONBytes, err = json.Marshal(cTopics)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodPost, routeRelayV1AutoSubscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusBadRequest, rr.Code)
|
||||
|
||||
}
|
||||
|
||||
func TestRelayGetV1AutoMessages(t *testing.T) {
|
||||
router := chi.NewRouter()
|
||||
router1 := chi.NewRouter()
|
||||
|
||||
serviceA := makeRelayService(t, router)
|
||||
|
||||
serviceB := makeRelayService(t, router1)
|
||||
|
||||
hostInfo, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", serviceB.node.Host().ID().String()))
|
||||
require.NoError(t, err)
|
||||
|
||||
var addr multiaddr.Multiaddr
|
||||
for _, a := range serviceB.node.Host().Addrs() {
|
||||
addr = a.Encapsulate(hostInfo)
|
||||
break
|
||||
}
|
||||
err = serviceA.node.DialPeerWithMultiAddress(context.Background(), addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for the dial to complete
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
cTopic1 := "/toychat/1/huilong/proto"
|
||||
|
||||
cTopics := []string{cTopic1}
|
||||
topicsJSONBytes, err := json.Marshal(cTopics)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, routeRelayV1AutoSubscriptions, bytes.NewReader(topicsJSONBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
require.Equal(t, "true", rr.Body.String())
|
||||
|
||||
// Wait for the subscription to be started
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
msg := &RestWakuMessage{
|
||||
Payload: []byte{1, 2, 3},
|
||||
ContentTopic: cTopic1,
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
msgJsonBytes, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodPost, routeRelayV1AutoMessages, bytes.NewReader(msgJsonBytes))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
// Wait for the message to be received
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", routeRelayV1AutoMessages, url.QueryEscape(cTopic1)), bytes.NewReader([]byte{}))
|
||||
router.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
var messages []*pb.WakuMessage
|
||||
err = json.Unmarshal(rr.Body.Bytes(), &messages)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, messages, 1)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", routeRelayV1AutoMessages, url.QueryEscape(cTopic1)), bytes.NewReader([]byte{}))
|
||||
router1.ServeHTTP(rr, req)
|
||||
require.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
}
|
||||
@ -1,189 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_store"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/store"
|
||||
storepb "github.com/waku-org/go-waku/waku/v2/protocol/store/pb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type StoreQueryService struct {
|
||||
node *node.WakuNode
|
||||
mux *chi.Mux
|
||||
}
|
||||
|
||||
const routeStoreMessagesV1 = "/store/v3/messages"
|
||||
|
||||
func NewStoreQueryService(node *node.WakuNode, m *chi.Mux) *StoreQueryService {
|
||||
s := &StoreQueryService{
|
||||
node: node,
|
||||
mux: m,
|
||||
}
|
||||
|
||||
m.Get(routeStoreMessagesV1, s.getV3Messages)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func getStoreParams(r *http.Request) (store.Criteria, []store.RequestOption, error) {
|
||||
var options []store.RequestOption
|
||||
var err error
|
||||
peerAddrStr := r.URL.Query().Get("peerAddr")
|
||||
var m multiaddr.Multiaddr
|
||||
if peerAddrStr != "" {
|
||||
m, err = multiaddr.NewMultiaddr(peerAddrStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
options = append(options, store.WithPeerAddr(m))
|
||||
}
|
||||
|
||||
includeData := false
|
||||
includeDataStr := r.URL.Query().Get("includeData")
|
||||
if includeDataStr != "" {
|
||||
includeData, err = strconv.ParseBool(includeDataStr)
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("invalid value for includeData. Use true|false")
|
||||
}
|
||||
}
|
||||
options = append(options, store.IncludeData(includeData))
|
||||
|
||||
pubsubTopic := r.URL.Query().Get("pubsubTopic")
|
||||
|
||||
contentTopics := r.URL.Query().Get("contentTopics")
|
||||
var contentTopicsArr []string
|
||||
if contentTopics != "" {
|
||||
contentTopicsArr = strings.Split(contentTopics, ",")
|
||||
}
|
||||
|
||||
hashesStr := r.URL.Query().Get("hashes")
|
||||
var hashes []pb.MessageHash
|
||||
if hashesStr != "" {
|
||||
hashesStrArr := strings.Split(hashesStr, ",")
|
||||
for _, hashStr := range hashesStrArr {
|
||||
hash, err := base64.URLEncoding.DecodeString(hashStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
hashes = append(hashes, pb.ToMessageHash(hash))
|
||||
}
|
||||
}
|
||||
|
||||
isMsgHashCriteria := false
|
||||
if len(hashes) != 0 {
|
||||
isMsgHashCriteria = true
|
||||
if pubsubTopic != "" || len(contentTopics) != 0 {
|
||||
return nil, nil, errors.New("cant use content filters while specifying message hashes")
|
||||
}
|
||||
} else {
|
||||
if pubsubTopic == "" || len(contentTopicsArr) == 0 {
|
||||
return nil, nil, errors.New("pubsubTopic and contentTopics are required")
|
||||
}
|
||||
}
|
||||
|
||||
startTimeStr := r.URL.Query().Get("startTime")
|
||||
var startTime *int64
|
||||
if startTimeStr != "" {
|
||||
startTimeValue, err := strconv.ParseInt(startTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
startTime = &startTimeValue
|
||||
}
|
||||
|
||||
endTimeStr := r.URL.Query().Get("endTime")
|
||||
var endTime *int64
|
||||
if endTimeStr != "" {
|
||||
endTimeValue, err := strconv.ParseInt(endTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
endTime = &endTimeValue
|
||||
}
|
||||
|
||||
var cursor []byte
|
||||
cursorStr := r.URL.Query().Get("cursor")
|
||||
if cursorStr != "" {
|
||||
cursor, err = base64.URLEncoding.DecodeString(cursorStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
options = append(options, store.WithCursor(cursor))
|
||||
}
|
||||
|
||||
pageSizeStr := r.URL.Query().Get("pageSize")
|
||||
ascendingStr := r.URL.Query().Get("ascending")
|
||||
if ascendingStr != "" || pageSizeStr != "" {
|
||||
ascending := true
|
||||
pageSize := uint64(legacy_store.DefaultPageSize)
|
||||
if ascendingStr != "" {
|
||||
ascending, err = strconv.ParseBool(ascendingStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if pageSizeStr != "" {
|
||||
pageSize, err = strconv.ParseUint(pageSizeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if pageSize > legacy_store.MaxPageSize {
|
||||
pageSize = legacy_store.MaxPageSize
|
||||
}
|
||||
}
|
||||
|
||||
options = append(options, store.WithPaging(ascending, pageSize))
|
||||
}
|
||||
|
||||
var query store.Criteria
|
||||
if isMsgHashCriteria {
|
||||
query = store.MessageHashCriteria{
|
||||
MessageHashes: hashes,
|
||||
}
|
||||
} else {
|
||||
query = store.FilterCriteria{
|
||||
ContentFilter: protocol.NewContentFilter(pubsubTopic, contentTopicsArr...),
|
||||
TimeStart: startTime,
|
||||
TimeEnd: endTime,
|
||||
}
|
||||
}
|
||||
|
||||
return query, options, nil
|
||||
}
|
||||
|
||||
func writeStoreError(w http.ResponseWriter, code int, err error) {
|
||||
writeResponse(w, &storepb.StoreQueryResponse{StatusCode: proto.Uint32(uint32(code)), StatusDesc: proto.String(err.Error())}, code)
|
||||
}
|
||||
|
||||
func (d *StoreQueryService) getV3Messages(w http.ResponseWriter, r *http.Request) {
|
||||
query, options, err := getStoreParams(r)
|
||||
if err != nil {
|
||||
writeStoreError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result, err := d.node.Store().Request(ctx, query, options...)
|
||||
if err != nil {
|
||||
writeLegacyStoreError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeErrOrResponse(w, nil, result.Response())
|
||||
}
|
||||
@ -1,135 +0,0 @@
|
||||
# /store/v3/messages:
|
||||
get:
|
||||
summary: Gets message history
|
||||
description: >
|
||||
Retrieves Waku message history. The returned history
|
||||
can be potentially filtered by optional request parameters.
|
||||
operationId: getMessageHistory
|
||||
tags:
|
||||
- store
|
||||
parameters:
|
||||
- name: peerAddr
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: >
|
||||
P2P fully qualified peer multiaddress
|
||||
in the format `(ip4|ip6)/tcp/p2p/$peerId` and URL-encoded.
|
||||
example: '%2Fip4%2F127.0.0.1%2Ftcp%2F60001%2Fp2p%2F16Uiu2HAmVFXtAfSj4EiR7mL2KvL4EE2wztuQgUSBoj2Jx2KeXFLN'
|
||||
|
||||
- name: includeData
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
Boolean indicating if the query should return messages (data) or hashes only.
|
||||
A value of 'false' returns hashes only.
|
||||
A value of 'true' returns hashes AND messages.
|
||||
Default value is 'false'
|
||||
example: 'true'
|
||||
|
||||
- name: pubsubTopic
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
The pubsub topic on which a WakuMessage is published.
|
||||
If left empty, no filtering is applied.
|
||||
It is also intended for pagination purposes.
|
||||
It should be a URL-encoded string.
|
||||
example: 'my%20pubsub%20topic'
|
||||
|
||||
- name: contentTopics
|
||||
in: query
|
||||
schema: string
|
||||
description: >
|
||||
Comma-separated list of content topics. When specified,
|
||||
only WakuMessages that are linked to any of the given
|
||||
content topics will be delivered in the get response.
|
||||
It should be a URL-encoded-comma-separated string.
|
||||
example: 'my%20first%20content%20topic%2Cmy%20second%20content%20topic%2Cmy%20third%20content%20topic'
|
||||
|
||||
- name: startTime
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
The inclusive lower bound on the timestamp of
|
||||
queried WakuMessages. This field holds the
|
||||
Unix epoch time in nanoseconds as a 64-bits
|
||||
integer value.
|
||||
example: '1680590945000000000'
|
||||
|
||||
- name: endTime
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
The inclusive upper bound on the timestamp of
|
||||
queried WakuMessages. This field holds the
|
||||
Unix epoch time in nanoseconds as a 64-bits
|
||||
integer value.
|
||||
example: '1680590945000000000'
|
||||
|
||||
- name: hashes
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
Comma-separated list of message hashes.
|
||||
URL-base64-encoded string computed as a hash of messages.
|
||||
Used to find messages by hash.
|
||||
example: 'Gc4ACThW5t2QQO82huq3WnDv%2FapPPJpD%2FwJfxDxAnR0%3D'
|
||||
|
||||
- name: cursor
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
Cursor field intended for pagination purposes.
|
||||
URL-base64-encoded string computed as a hash of a message.
|
||||
It could be empty for retrieving the first page,
|
||||
and will be returned from the GET response so that
|
||||
it can be part of the next page request.
|
||||
example: 'Gc4ACThW5t2QQO82huq3WnDv%2FapPPJpD%2FwJfxDxAnR0%3D'
|
||||
|
||||
- name: pageSize
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
Number of messages to retrieve per page
|
||||
example: '5'
|
||||
|
||||
- name: ascending
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: >
|
||||
"true" for paging forward, "false" for paging backward.
|
||||
If not specified or if specified with an invalid value, the default is "true".
|
||||
example: "true"
|
||||
|
||||
responses:
|
||||
'200':
|
||||
description: Waku message history.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/StoreQueryResponse'
|
||||
'400':
|
||||
description: Bad request error.
|
||||
content:
|
||||
text/plain:
|
||||
type: string
|
||||
'412':
|
||||
description: Precondition failed.
|
||||
content:
|
||||
text/plain:
|
||||
type: string
|
||||
'500':
|
||||
description: Internal server error.
|
||||
content:
|
||||
text/plain:
|
||||
type: string
|
||||
@ -1,83 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// The functions writes error response in plain text format with specified statusCode
|
||||
func writeErrResponse(w http.ResponseWriter, log *zap.Logger, err error, statusCode int) {
|
||||
w.WriteHeader(statusCode)
|
||||
_, err = w.Write([]byte(err.Error()))
|
||||
if err != nil {
|
||||
log.Error("error while writing response", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// This function writes error or response in json format with statusCode as 500 in case of error
|
||||
func writeErrOrResponse(w http.ResponseWriter, err error, value interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
jsonResponse, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = w.Write(jsonResponse)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// This function writes a response in json format
|
||||
func writeResponse(w http.ResponseWriter, value interface{}, code int) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
jsonResponse, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// w.Write implicitly writes a 200 status code
|
||||
// and only once we can write 2xx-5xx status code
|
||||
// so any statusCode apart from 1xx being written to the header, will be ignored.
|
||||
w.WriteHeader(code)
|
||||
_, _ = w.Write(jsonResponse)
|
||||
}
|
||||
|
||||
func topicFromPath(w http.ResponseWriter, req *http.Request, field string, logger *zap.Logger) string {
|
||||
topic := chi.URLParam(req, field)
|
||||
if topic == "" {
|
||||
errMissing := fmt.Errorf("missing %s", field)
|
||||
writeGetMessageErr(w, errMissing, http.StatusBadRequest, logger)
|
||||
return ""
|
||||
}
|
||||
topic, err := url.QueryUnescape(topic)
|
||||
if err != nil {
|
||||
errInvalid := fmt.Errorf("invalid %s format", field)
|
||||
writeGetMessageErr(w, errInvalid, http.StatusBadRequest, logger)
|
||||
return ""
|
||||
}
|
||||
return topic
|
||||
}
|
||||
|
||||
func writeGetMessageErr(w http.ResponseWriter, err error, code int, logger *zap.Logger) {
|
||||
// write status before the body
|
||||
w.WriteHeader(code)
|
||||
logger.Error("get message", zap.Error(err))
|
||||
if _, err := w.Write([]byte(err.Error())); err != nil {
|
||||
logger.Error("writing response", zap.Error(err))
|
||||
}
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type WakuRest struct {
|
||||
node *node.WakuNode
|
||||
server *http.Server
|
||||
|
||||
log *zap.Logger
|
||||
|
||||
relayService *RelayService
|
||||
filterService *FilterService
|
||||
}
|
||||
|
||||
type RestConfig struct {
|
||||
Address string
|
||||
Port uint
|
||||
EnablePProf bool
|
||||
EnableAdmin bool
|
||||
RelayCacheCapacity uint
|
||||
FilterCacheCapacity uint
|
||||
}
|
||||
|
||||
func NewWakuRest(node *node.WakuNode, config RestConfig, log *zap.Logger) *WakuRest {
|
||||
wrpc := new(WakuRest)
|
||||
wrpc.log = log.Named("rest")
|
||||
|
||||
mux := chi.NewRouter()
|
||||
mux.Use(middleware.Logger)
|
||||
mux.Use(middleware.NoCache)
|
||||
mux.Use(func(h http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
return http.HandlerFunc(fn)
|
||||
})
|
||||
if config.EnablePProf {
|
||||
mux.Mount("/debug", middleware.Profiler())
|
||||
}
|
||||
|
||||
_ = NewDebugService(node, mux)
|
||||
_ = NewHealthService(node, mux)
|
||||
_ = NewStoreQueryService(node, mux)
|
||||
_ = NewLegacyStoreService(node, mux)
|
||||
_ = NewLightpushService(node, mux, log)
|
||||
|
||||
listenAddr := fmt.Sprintf("%s:%d", config.Address, config.Port)
|
||||
|
||||
server := &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: mux,
|
||||
}
|
||||
|
||||
wrpc.node = node
|
||||
wrpc.server = server
|
||||
|
||||
if node.Relay() != nil {
|
||||
relayService := NewRelayService(node, mux, config.RelayCacheCapacity, log)
|
||||
wrpc.relayService = relayService
|
||||
}
|
||||
|
||||
if config.EnableAdmin {
|
||||
_ = NewAdminService(node, mux, wrpc.log)
|
||||
}
|
||||
|
||||
if node.FilterLightnode() != nil {
|
||||
filterService := NewFilterService(node, mux, int(config.FilterCacheCapacity), log)
|
||||
server.RegisterOnShutdown(func() {
|
||||
filterService.Stop()
|
||||
})
|
||||
wrpc.filterService = filterService
|
||||
}
|
||||
|
||||
return wrpc
|
||||
}
|
||||
|
||||
func (r *WakuRest) Start(ctx context.Context, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if r.node.FilterLightnode() != nil {
|
||||
go r.filterService.Start(ctx)
|
||||
}
|
||||
|
||||
go func() {
|
||||
_ = r.server.ListenAndServe()
|
||||
}()
|
||||
r.log.Info("server started", zap.String("addr", r.server.Addr))
|
||||
}
|
||||
|
||||
func (r *WakuRest) Stop(ctx context.Context) error {
|
||||
r.log.Info("shutting down server")
|
||||
return r.server.Shutdown(ctx)
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
//go:build !gowaku_no_rln
|
||||
// +build !gowaku_no_rln
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln"
|
||||
)
|
||||
|
||||
func AppendRLNProof(node *node.WakuNode, msg *pb.WakuMessage) error {
|
||||
_, rlnEnabled := node.RLNRelay().(*rln.WakuRLNRelay)
|
||||
if rlnEnabled {
|
||||
err := node.RLNRelay().AppendRLNProof(msg, node.Timesource().Now())
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not append rln proof: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_store"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/store"
|
||||
)
|
||||
|
||||
func IsWakuProtocol(protocol protocol.ID) bool {
|
||||
return protocol == filter.FilterPushID_v20beta1 ||
|
||||
protocol == filter.FilterSubscribeID_v20beta1 ||
|
||||
protocol == relay.WakuRelayID_v200 ||
|
||||
protocol == lightpush.LightPushID_v20beta1 ||
|
||||
protocol == legacy_store.StoreID_v20beta4 ||
|
||||
protocol == store.StoreQueryID_v300
|
||||
}
|
||||
|
||||
type Base64URLByte []byte
|
||||
|
||||
// UnmarshalText is used by json.Unmarshal to decode both url-safe and standard
|
||||
// base64 encoded strings with and without padding
|
||||
func (h *Base64URLByte) UnmarshalText(b []byte) error {
|
||||
inputValue := ""
|
||||
if b != nil {
|
||||
inputValue = string(b)
|
||||
}
|
||||
|
||||
enc := base64.StdEncoding
|
||||
if strings.ContainsAny(inputValue, "-_") {
|
||||
enc = base64.URLEncoding
|
||||
}
|
||||
if len(inputValue)%4 != 0 {
|
||||
enc = enc.WithPadding(base64.NoPadding)
|
||||
}
|
||||
|
||||
decodedBytes, err := enc.DecodeString(inputValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*h = decodedBytes
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
//go:build !linux && !darwin && !windows
|
||||
|
||||
package main
|
||||
|
||||
import "runtime"
|
||||
|
||||
// TODO: figure out how to get the number of file descriptors on Windows and other systems
|
||||
func getNumFDs() int {
|
||||
fmt.Println("cannot determine number of file descriptors on ", runtime.GOOS)
|
||||
return 0
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
//go:build linux || darwin
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func getNumFDs() int {
|
||||
var l unix.Rlimit
|
||||
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &l); err != nil {
|
||||
fmt.Println("failed to get fd limit:" + err.Error())
|
||||
return 0
|
||||
}
|
||||
return int(l.Cur)
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
func getNumFDs() int {
|
||||
return math.MaxInt
|
||||
}
|
||||
33
default.nix
33
default.nix
@ -1,33 +0,0 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
self ? ./.,
|
||||
subPkgs ? "cmd/waku",
|
||||
ldflags ? [],
|
||||
output ? null,
|
||||
commit ? builtins.substring 0 7 (self.rev or "dirty"),
|
||||
version ? builtins.readFile ./VERSION,
|
||||
}:
|
||||
|
||||
pkgs.buildGo123Module {
|
||||
name = "go-waku";
|
||||
src = self;
|
||||
|
||||
subPackages = subPkgs;
|
||||
tags = ["gowaku_no_rln"];
|
||||
ldflags = [
|
||||
"-X github.com/waku-org/go-waku/waku/v2/node.GitCommit=${commit}"
|
||||
"-X github.com/waku-org/go-waku/waku/v2/node.Version=${version}"
|
||||
] ++ ldflags;
|
||||
doCheck = false;
|
||||
|
||||
# Otherwise library would be just called bin/c.
|
||||
postInstall = if builtins.isString output then ''
|
||||
mv $out/bin/* $out/bin/${output}
|
||||
'' else "";
|
||||
|
||||
# FIXME: This needs to be manually changed when updating modules.
|
||||
vendorHash = "sha256-uz9IVTEd+3UypZQc2CVWCFeLE4xEagn9YT9W2hr0K/o=";
|
||||
|
||||
# Fix for 'nix run' trying to execute 'go-waku'.
|
||||
meta = { mainProgram = "waku"; };
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
# BUILD IMAGE --------------------------------------------------------
|
||||
FROM golang:1.20 as builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
# Build the final node binary
|
||||
RUN make -j$(nproc) build
|
||||
|
||||
# ACTUAL IMAGE -------------------------------------------------------
|
||||
|
||||
FROM debian:12.1-slim
|
||||
|
||||
LABEL maintainer="romanzac@status.im"
|
||||
LABEL source="https://github.com/waku-org/go-waku"
|
||||
LABEL description="go-waku: Waku V2 node - test"
|
||||
|
||||
# color, nocolor, json
|
||||
ENV GOLOG_LOG_FMT=nocolor
|
||||
|
||||
RUN apt update && apt install -y ca-certificates
|
||||
|
||||
# go-waku default ports
|
||||
EXPOSE 9000 30303 60000 60001 8008 8009
|
||||
|
||||
COPY --from=builder /app/build/waku /usr/bin/waku
|
||||
|
||||
ENTRYPOINT ["/usr/bin/waku"]
|
||||
# By default just show help if called without arguments
|
||||
CMD ["--help"]
|
||||
@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
discoveryURL := "enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im"
|
||||
discoveryURL := "enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im"
|
||||
nodes, err := dnsdisc.RetrieveNodes(context.Background(), discoveryURL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -40,4 +40,4 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
`dnsdisc.RetrieveNodes` can also accept a `WithNameserver(nameserver string)` option which can be used to specify the nameserver to use to retrieve the TXT record from the domain name
|
||||
`dnsdisc.RetrieveNodes` can also accept a `WithNameserver(nameserver string)` option which can be used to specify the nameserver to use to retrieve the TXT record from the domain name
|
||||
@ -15,13 +15,15 @@ import (
|
||||
)
|
||||
|
||||
...
|
||||
wakuNode, err := node.New(node.WithWakuFilter(false))
|
||||
wakuNode, err := node.New(context.Background(),
|
||||
node.WithWakuFilter(false),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := wakuNode.Start(context.Background()); err != nil {
|
||||
if err := wakuNode.Start(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
@ -38,7 +40,7 @@ One of these options must be specified when instantiating a node supporting the
|
||||
```go
|
||||
...
|
||||
|
||||
peerAddr, err := multiaddr.NewMultiaddr("/dns4/node-01.do-ams3.waku.test.status.im/tcp/30303/p2p/16Uiu2HAkykgaECHswi3YKJ5dMLbq2kPVCo89fcyTd38UcQD6ej5W")
|
||||
peerAddr, err := multiaddr.NewMultiaddr("/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -25,13 +25,15 @@ import (
|
||||
)
|
||||
|
||||
...
|
||||
wakuNode, err := node.New(node.WithLightPush())
|
||||
wakuNode, err := node.New(context.Background(),
|
||||
node.WithLightPush(),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := wakuNode.Start(context.Background()); err != nil {
|
||||
if err := wakuNode.Start(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
@ -65,17 +67,22 @@ if err != nil {
|
||||
```
|
||||
|
||||
|
||||
To send a message, it needs to be wrapped into a [`WakuMessage`](https://rfc.vac.dev/spec/14/) protobuffer.
|
||||
The payload of the message is not limited to strings. Any kind of data that can be serialized
|
||||
To send a message, it needs to be wrapped into a [`WakuMessage`](https://rfc.vac.dev/spec/14/) protobuffer. The payload of the message is not limited to strings. Any kind of data that can be serialized
|
||||
into a `[]byte` can be sent as long as it does not exceed the maximum length a message can have (~1MB)
|
||||
|
||||
`wakuNode.Lightpush().Publish(ctx, msg, opts...)` is used to publish a message. This function will return a message id on success, or an error if the message could not be published.
|
||||
The following functions can be used to publish a message:
|
||||
- `wakuNode.Lightpush().Publish(ctx, msg, opts...)` - to send a message to the default waku pubsub topic
|
||||
- `wakuNode.Lightpush().PublishToTopic(ctx, msg, topic, opts...)` - to send a message to a custom pubsub topic
|
||||
|
||||
If no options are specified, go-waku will automatically choose the peer used to broadcast the message via Lightpush and publish the message to a pubsub topic derived from the content topic of the message. This behaviour can be controlled via options:
|
||||
Both of these functions will return a message id on success, or an error if the message could not be published.
|
||||
|
||||
If no options are specified, go-waku will automatically choose the peer used to broadcast the message via Lightpush. This behaviour can be controlled via options:
|
||||
|
||||
### Options
|
||||
- `lightpush.WithPubSubTopic(topic)` - broadcast the message using a custom pubsub topic
|
||||
- `lightpush.WithDefaultPubsubTopic()` - broadcast the message to the default pubsub topic
|
||||
|
||||
- `lightpush.WithPeer(peerID)` - use an specific peer ID (which should be part of the node peerstore) to broadcast the message with
|
||||
- `lightpush.WithAutomaticPeerSelection(host)` - automatically select a peer that supports lightpush protocol from the peerstore to broadcast the message with
|
||||
- `lightpush.WithFastestPeerSelection(ctx)` - automatically select a peer based on its ping reply time
|
||||
|
||||
|
||||
|
||||
|
||||
@ -16,13 +16,15 @@ import (
|
||||
)
|
||||
|
||||
...
|
||||
wakuNode, err := node.New(node.WithWakuRelay())
|
||||
wakuNode, err := node.New(context.Background(),
|
||||
node.WithWakuRelay(),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := wakuNode.Start(context.Background()); err != nil {
|
||||
if err := wakuNode.Start(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
@ -41,19 +43,34 @@ One of these options must be specified when instantiating a node supporting the
|
||||
## Receiving messages
|
||||
```go
|
||||
...
|
||||
contentFilter := protocol.NewContentFilter(relay.DefaultWakuTopic)
|
||||
sub, err := wakuNode.Relay().Subscribe(context.Background, contentFilter) ([]*Subscription, error)
|
||||
sub, err := wakuNode.Relay().Subscribe(context.Background())
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for value := range sub[0].C {
|
||||
for value := range sub.C {
|
||||
fmt.Println("Received msg:", string(value.Message().Payload))
|
||||
}
|
||||
...
|
||||
```
|
||||
To receive messages sent via the relay protocol, you need to subscribe specifying a content filter with the function `Subscribe(ctx context.Context, contentFilter waku_proto.ContentFilter, opts ...RelaySubscribeOption) ([]*Subscription, error)`. This functions return a list of `Subscription` struct containing a channel on which messages will be received. To stop receiving messages `WakuRelay`'s `Unsubscribe(ctx context.Context, contentFilter waku_proto.ContentFilter) error` can be executed which will close the channel (without unsubscribing from the pubsub topic) which will make sure the subscription is stopped, and if no other subscriptions exist for underlying pubsub topic, the pubsub is also unsubscribed.
|
||||
To receive messages sent via the relay protocol, you need to subscribe to a pubsub topic. This can be done via any of these functions:
|
||||
- `wakuNode.Relay().Subscribe(ctx)` - subscribes to the default waku pubsub topic `/waku/2/default-waku/proto`
|
||||
- `wakuNode.Relay().SubscribeToTopic(ctx, topic)` - subscribes to a custom pubsub topic
|
||||
|
||||
These functions return a `Subscription` struct containing a channel on which messages will be received. To stop receiving messages in this channel `sub.Unsubscribe()` can be executed which will close the channel (without unsubscribing from the pubsub topic)
|
||||
|
||||
> Pubsub topics should follow the [recommended usage](https://rfc.vac.dev/spec/23/) structure. For this purpose, the `NewPubsubTopic` helper function was created:
|
||||
```go
|
||||
import "github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
|
||||
topic := protocol.NewPubsubTopic("the_topic_name", "the_encoding")
|
||||
/*
|
||||
fmt.Println(topic.String()) // => `/waku/2/the_topic_name/the_encoding`
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Sending messages
|
||||
|
||||
@ -80,13 +97,11 @@ if err != nil {
|
||||
To send a message, it needs to be wrapped into a [`WakuMessage`](https://rfc.vac.dev/spec/14/) protobuffer. The payload of the message is not limited to strings. Any kind of data that can be serialized
|
||||
into a `[]byte` can be sent as long as it does not exceed the maximum length a message can have (~1MB)
|
||||
|
||||
`wakuNode.Relay().Publish(ctx, msg, opts...)` is used to publish a message. This function will return a message id on success, or an error if the message could not be published.
|
||||
The following functions can be used to publish a message:
|
||||
- `wakuNode.Relay().Publish(ctx, msg)` - to send a message to the default waku pubsub topic
|
||||
- `wakuNode.Relay().PublishToTopic(ctx, msg, topic)` - to send a message to a custom pubsub topic
|
||||
|
||||
If no options are specified, go-waku will automatically choose the peer used to broadcast the message via Relay and publish the message to a pubsub topic derived from the content topic of the message. This behaviour can be controlled via options:
|
||||
|
||||
### Options
|
||||
- `relay.WithPubSubTopic(topic)` - broadcast the message using a custom pubsub topic
|
||||
- `relay.WithDefaultPubsubTopic()` - broadcast the message to the default pubsub topic
|
||||
Both of these functions will return a message id on success, or an error if the message could not be published.
|
||||
|
||||
> If `WithWakuRelayAndMinPeers` was used during the instantiation of the wakuNode, it should be possible to verify if there's enough peers for publishing to a topic with `wakuNode.Relay().EnoughPeersToPublish()` and `wakuNode.Relay().EnoughPeersToPublishToTopic(topic)`
|
||||
|
||||
|
||||
@ -28,14 +28,19 @@ if err != nil {
|
||||
// Handle error ...
|
||||
}
|
||||
|
||||
for !result.IsComplete() {
|
||||
for _, msg := range result.GetMessages() {
|
||||
// Do something with the messages
|
||||
}
|
||||
|
||||
err := result.Next(ctx)
|
||||
for {
|
||||
hasNext, err := result.Next(ctx)
|
||||
if err != nil {
|
||||
// Handle error ...
|
||||
break
|
||||
}
|
||||
|
||||
if !hasNext { // No more messages available
|
||||
break
|
||||
}
|
||||
|
||||
for _, msg := range result.GetMessages() {
|
||||
// Do something with the messages
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -4,7 +4,7 @@ Go-waku can be built on Linux, macOS and Windows
|
||||
|
||||
## Installing dependencies
|
||||
|
||||
Cloning and building go-waku requires Go +1.19, a C compiler, Make, Bash and Git.
|
||||
Cloning and building go-waku requires Go +1.17, a C compiler, Make, Bash and Git.
|
||||
|
||||
Go can be installed by following [these instructions](https://go.dev/doc/install)
|
||||
|
||||
@ -31,13 +31,13 @@ Assuming you use [Homebrew](https://brew.sh/) to manage packages
|
||||
brew install cmake
|
||||
```
|
||||
|
||||
## Building go-waku
|
||||
## Building nwaku
|
||||
|
||||
### 1. Clone the go-waku repository
|
||||
### 1. Clone the nwaku repository
|
||||
|
||||
```sh
|
||||
git clone https://github.com/waku-org/go-waku
|
||||
cd go-waku
|
||||
cd nwaku
|
||||
```
|
||||
|
||||
### 2. Build waku
|
||||
|
||||
@ -24,7 +24,7 @@ A node will attempt connection to all discovered nodes.
|
||||
|
||||
This can be used, for example, to connect to one of the existing fleets.
|
||||
Current URLs for the published fleet lists:
|
||||
- production fleet: `enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im`
|
||||
- test fleet: `enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im`
|
||||
- production fleet: `enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@prod.waku.nodes.status.im`
|
||||
- test fleet: `enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im`
|
||||
|
||||
See the [separate tutorial](../../tutorial/dns-disc.md) for a complete guide to DNS discovery.
|
||||
See the [separate tutorial](../../tutorial/dns-disc.md) for a complete guide to DNS discovery.
|
||||
@ -17,12 +17,12 @@ or store and serve historical messages itself.
|
||||
|
||||
Ensure that `store` is enabled (this is `true` by default) and provide at least one store service node address with the `--storenode` CLI option.
|
||||
|
||||
See the following example, using the peer at `/dns4/node-01.ac-cn-hongkong-c.waku.test.status.im/tcp/30303/p2p/16Uiu2HAkzHaTP5JsUwfR9NR8Rj9HC24puS6ocaU8wze4QrXr9iXp` as store service node.
|
||||
See the following example, using the peer at `/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm` as store service node.
|
||||
|
||||
```sh
|
||||
./build/waku \
|
||||
--store=true \
|
||||
--storenode=/dns4/node-01.ac-cn-hongkong-c.waku.test.status.im/tcp/30303/p2p/16Uiu2HAkzHaTP5JsUwfR9NR8Rj9HC24puS6ocaU8wze4QrXr9iXp
|
||||
--storenode=/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm
|
||||
```
|
||||
|
||||
Your node can now send queries to retrieve historical messages
|
||||
|
||||
@ -1,74 +0,0 @@
|
||||
# How to run spam prevention on your go-waku node (RLN)
|
||||
|
||||
This guide explains how to run a go-waku node with RLN (Rate Limiting Nullifier) enabled.
|
||||
|
||||
[RLN](https://rfc.vac.dev/spec/32/) is a protocol integrated into waku v2,
|
||||
which prevents spam-based attacks on the network.
|
||||
|
||||
For further background on the research for RLN tailored to waku, refer
|
||||
to [this](https://rfc.vac.dev/spec/17/) RFC.
|
||||
|
||||
Registering to the membership group has been left out for brevity.
|
||||
If you would like to register to the membership group and send messages with RLN,
|
||||
refer to the [on-chain chat2 tutorial](../../tutorial/onchain-rln-relay-chat2.md).
|
||||
|
||||
This guide specifically allows a node to participate in RLN testnet
|
||||
You may alter the rln-specific arguments as required.
|
||||
|
||||
|
||||
## 1. Update the runtime arguments
|
||||
|
||||
Follow the steps from the [build](./build.md) and [run](./run.md) guides while replacing the run command with -
|
||||
|
||||
```bash
|
||||
export WAKU_FLEET=<enrtree of the fleet>
|
||||
export SEPOLIA_WS_NODE_ADDRESS=<WS RPC URL to a Sepolia Node>
|
||||
export RLN_RELAY_CONTRACT_ADDRESS="0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4" # Replace this with any compatible implementation
|
||||
$WAKUNODE_DIR/build/waku \
|
||||
--dns-discovery \
|
||||
--dns-discovery-url="$WAKU_FLEET" \
|
||||
--discv5-discovery=true \
|
||||
--rln-relay=true \
|
||||
--rln-relay-dynamic=true \
|
||||
--rln-relay-eth-contract-address="$RLN_RELAY_CONTRACT_ADDRESS" \
|
||||
--rln-relay-eth-client-address="$SEPOLIA_WS_NODE_ADDRESS"
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
If you installed go-waku using a `.dpkg` or `.rpm` package, you can use the `waku` command instead of building go-waku yourself
|
||||
|
||||
OR
|
||||
|
||||
If you have the go-waku node within docker, you can replace the run command with -
|
||||
|
||||
```bash
|
||||
export WAKU_FLEET=<enrtree of the fleet>
|
||||
export SEPOLIA_WS_NODE_ADDRESS=<WS RPC URL to a Sepolia Node>
|
||||
export RLN_RELAY_CONTRACT_ADDRESS="0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4" # Replace this with any compatible implementation
|
||||
docker run -i -t -p 60000:60000 -p 9000:9000/udp \
|
||||
-v /absolute/path/to/your/rlnKeystore.json:/rlnKeystore.json:ro \
|
||||
wakuorg/go-waku:latest \
|
||||
--dns-discovery=true \
|
||||
--dns-discovery-url="$WAKU_FLEET" \
|
||||
--discv5-discovery \
|
||||
--rln-relay=true \
|
||||
--rln-relay-dynamic=true \
|
||||
--rln-relay-eth-contract-address="$RLN_RELAY_CONTRACT_ADDRESS" \
|
||||
--rln-relay-eth-client-address="$SEPOLIA_WS_NODE_ADDRESS"
|
||||
```
|
||||
|
||||
Following is the list of additional fields that have been added to the
|
||||
runtime arguments -
|
||||
|
||||
1. `--rln-relay`: Allows waku-rln-relay to be mounted into the setup of the go-waku node. All messages sent and received in this node will require to contain a valid proof that will be verified, and nodes that relay messages with invalid proofs will have their peer scoring affected negatively and will be eventually disconnected.
|
||||
2. `--rln-relay-dynamic`: Enables waku-rln-relay to connect to an ethereum node to fetch the membership group
|
||||
3. `--rln-relay-eth-contract-address`: The contract address of an RLN membership group
|
||||
4. `--rln-relay-eth-client-address`: The websocket url to a Sepolia ethereum node
|
||||
|
||||
The `--dns-discovery-url` flag should contain a valid URL with nodes encoded according to EIP-1459. You can read more about DNS Discovery [here](https://github.com/waku-org/nwaku/blob/master/docs/tutorial/dns-disc.md)
|
||||
|
||||
You should now have go-waku running, with RLN enabled!
|
||||
|
||||
|
||||
> Note: This guide will be updated in the future to include features like slashing.
|
||||
@ -17,13 +17,13 @@ See [this tutorial](./configure-key.md) if you want to generate and configure a
|
||||
- enable `relay` protocol
|
||||
- subscribe to the default pubsub topic, namely `/waku/2/default-waku/proto`
|
||||
- enable `store` protocol, but only as a client.
|
||||
This implies that the go-waku node will not persist any historical messages itself,
|
||||
This implies that the nwaku node will not persist any historical messages itself,
|
||||
but can query `store` service peers who do so.
|
||||
To configure `store` as a service node,
|
||||
see [this tutorial](./configure-store.md).
|
||||
|
||||
> **Note:** The `filter` and `lightpush` protocols are _not_ enabled by default.
|
||||
Consult the [configuration guide](./configure.md) on how to configure your go-waku node to run these protocols.
|
||||
Consult the [configuration guide](./configure.md) on how to configure your nwaku node to run these protocols.
|
||||
|
||||
Some typical non-default configurations are explained below.
|
||||
For more advanced configuration, see the [configuration guide](./configure.md).
|
||||
@ -33,7 +33,7 @@ Different ways to connect to other nodes are expanded upon in our [connection gu
|
||||
|
||||
Find the log entry beginning with `Listening on`.
|
||||
It should be printed at INFO level when you start your node
|
||||
and contains a list of all publically announced listening addresses for the go-waku node.
|
||||
and contains a list of all publically announced listening addresses for the nwaku node.
|
||||
|
||||
For example
|
||||
|
||||
@ -80,7 +80,7 @@ returns a response similar to
|
||||
|
||||
## Finding your discoverable ENR address(es)
|
||||
|
||||
A go-waku node can encode its addressing information in an [Ethereum Node Record (ENR)](https://eips.ethereum.org/EIPS/eip-778) according to [`31/WAKU2-ENR`](https://rfc.vac.dev/spec/31/).
|
||||
A nwaku node can encode its addressing information in an [Ethereum Node Record (ENR)](https://eips.ethereum.org/EIPS/eip-778) according to [`31/WAKU2-ENR`](https://rfc.vac.dev/spec/31/).
|
||||
These ENR are most often used for discovery purposes.
|
||||
|
||||
### ENR for DNS discovery and DiscV5
|
||||
@ -111,10 +111,10 @@ to continually discover and connect to random peers for a more robust mesh.
|
||||
|
||||
A typical run configuration for a go-waku node is to connect to existing peers with known listening addresses using the `--staticnode` option.
|
||||
The `--staticnode` option can be repeated for each peer you want to connect to on startup.
|
||||
This is also useful if you want to run several go-waku instances locally
|
||||
This is also useful if you want to run several nwaku instances locally
|
||||
and therefore know the listening addresses of all peers.
|
||||
|
||||
As an example, consider a go-waku node that connects to two known peers
|
||||
As an example, consider a nwaku node that connects to two known peers
|
||||
on the same local host (with IP `0.0.0.0`)
|
||||
with TCP ports `60002` and `60003`,
|
||||
and peer IDs `16Uiu2HAkzjwwgEAXfeGNMKFPSpc6vGBRqCdTLG5q3Gmk2v4pQw7H` and `16Uiu2HAmFBA7LGtwY5WVVikdmXVo3cKLqkmvVtuDu63fe8safeQJ` respectively.
|
||||
@ -130,7 +130,7 @@ We include an example below.
|
||||
```
|
||||
|
||||
|
||||
### Connecting to the `waku.sandbox` network
|
||||
### Connecting to the `wakuv2.prod` network
|
||||
|
||||
You can use DNS discovery to bootstrap connection to the existing production network.
|
||||
Discovery v5 will attempt to extract the ENRs of the discovered nodes as bootstrap entries to the routing table.
|
||||
@ -138,11 +138,11 @@ Discovery v5 will attempt to extract the ENRs of the discovered nodes as bootstr
|
||||
```sh
|
||||
./build/waku \
|
||||
--dns-discovery=true \
|
||||
--dns-discovery-url=enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im \
|
||||
--dns-discovery-url=enrtree://ANTL4SLG2COUILKAPE7EF2BYNL2SHSHVCHLRD5J7ZJLN5R3PRJD2Y@prod.waku.nodes.status.im \
|
||||
--discv5-discovery=true
|
||||
```
|
||||
|
||||
### Connecting to the `waku.test` network
|
||||
### Connecting to the `wakuv2.test` network
|
||||
|
||||
You can use DNS discovery to bootstrap connection to the existing test network.
|
||||
Discovery v5 will attempt to extract the ENRs of the discovered nodes as bootstrap entries to the routing table.
|
||||
@ -150,7 +150,7 @@ Discovery v5 will attempt to extract the ENRs of the discovered nodes as bootstr
|
||||
```sh
|
||||
./build/waku \
|
||||
--dns-discovery=true \
|
||||
--dns-discovery-url=enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im \
|
||||
--dns-discovery-url=enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im \
|
||||
--discv5-discovery=true
|
||||
```
|
||||
|
||||
@ -159,7 +159,7 @@ Discovery v5 will attempt to extract the ENRs of the discovered nodes as bootstr
|
||||
Often go-waku nodes choose to also store historical messages
|
||||
from where it can be queried by other peers who may have been temporarily offline.
|
||||
For example, a typical configuration for such a store service node,
|
||||
[connecting to the `waku.test`](#connecting-to-the-wakutest-network) fleet on startup,
|
||||
[connecting to the `wakuv2.test`](#connecting-to-the-wakuv2test-fleet) fleet on startup,
|
||||
appears below.
|
||||
|
||||
```sh
|
||||
@ -169,7 +169,7 @@ appears below.
|
||||
--db-path=/mnt/go-waku/data/db1/ \
|
||||
--store-capacity=150000 \
|
||||
--dns-discovery=true \
|
||||
--dns-discovery-url=enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im \
|
||||
--dns-discovery-url=enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im \
|
||||
--discv5-discovery=true
|
||||
```
|
||||
|
||||
@ -180,5 +180,5 @@ See our [store configuration tutorial](./configure-store.md) for more.
|
||||
A running go-waku node can be interacted with using the [Waku v2 JSON RPC API](https://rfc.vac.dev/spec/16/).
|
||||
|
||||
> **Note:** Private and Admin API functionality are disabled by default.
|
||||
To configure a go-waku node with these enabled,
|
||||
use the `--rpc-admin:true` and `--rpc-private:true` CLI options.
|
||||
To configure a nwaku node with these enabled,
|
||||
use the `--rpc-admin:true` and `--rpc-private:true` CLI options.
|
||||
@ -8,7 +8,7 @@ For a more advanced configuration see our [configuration guides](./how-to/config
|
||||
|
||||
[Build the go-waku node](./how-to/build.md)
|
||||
or download a precompiled binary from our [releases page](https://github.com/waku-org/go-waku/releases).
|
||||
<!-- Docker images are published to [wakuorg/go-waku](https://hub.docker.com/r/wakuorg/go-waku/tags) on DockerHub. -->
|
||||
<!-- Docker images are published to [statusteam/go-waku](https://hub.docker.com/r/statusteam/go-waku/tags) on DockerHub. -->
|
||||
<!-- TODO: more advanced explanation on finding and using docker images -->
|
||||
|
||||
## 2. Run
|
||||
@ -16,7 +16,7 @@ or download a precompiled binary from our [releases page](https://github.com/wak
|
||||
[Run the go-waku node](./how-to/run.md) using a default or common configuration
|
||||
or [configure](./how-to/configure.md) the node for more advanced use cases.
|
||||
|
||||
[Connect](./how-to/connect.md) the go-waku node to other peers to start communicating.
|
||||
[Connect](./how-to/connect.md) the nwaku node to other peers to start communicating.
|
||||
|
||||
## 3. Interact
|
||||
|
||||
|
||||
@ -1,111 +0,0 @@
|
||||
In this tutotial you will learn how to:
|
||||
1. Create Sepolia Ethereum Account and obtain its private key.
|
||||
2. Obtain Sepolia Ethers from faucet.
|
||||
3. Set up a hosted node on Sepolia Testnet using Infura.
|
||||
|
||||
If you already have an Ethereum account with sufficient ethers on the Sepolia testnet then you can skip the first two sections.
|
||||
## Creating Sepolia Ethereum Account and obtaining its private key
|
||||
|
||||
|
||||
1. Download and install Metamask. [https://metamask.io/download/](https://metamask.io/download/)
|
||||
2. Create a new wallet and save your secret recovery key.
|
||||
|
||||

|
||||
|
||||
3. Login to Metamask.
|
||||
|
||||

|
||||
|
||||
4. You should already see an account created. As you can see on top right, it should be pointing to Ethereum mainnet.
|
||||
|
||||

|
||||
|
||||
5. You can use the same account for different networks. For Waku we need to connect to the Sepolia test network.
|
||||
6. You can switch to a test network by clicking on the drop down menu. Select Sepolia test network for Waku:
|
||||
|
||||

|
||||
|
||||
7. Click on Show/hide test networks.
|
||||
8. Enable “Show Test Networks".
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
9. Close the settings and now you should see the test networks in the drop down on the top right.
|
||||
|
||||

|
||||
|
||||
10. Switch to Sepolia Test Network.
|
||||
11. You can see that the same account can be used with different networks. But note that the ETH balance on different networks are different and are different tokens.
|
||||
|
||||

|
||||
|
||||
12. Now to export your private key for the account, if needed, please click on the three dots beside the account.
|
||||
|
||||

|
||||
|
||||
13. Click on Account Details.
|
||||
14. Click on Export Private Key.
|
||||
|
||||

|
||||
|
||||
15. Enter your Metamask password when prompted.
|
||||
|
||||

|
||||
|
||||
16. You will be shown the private key. Copy it as needed.
|
||||
|
||||
Obtain Sepolia Ethers from faucet
|
||||
---
|
||||
|
||||
1. Ethers on Sepolia test networks can be obtained from different faucets.
|
||||
2. One of the faucets is as follows:
|
||||
1. [https://sepoliafaucet.com//](https://sepoliafaucet.com/)
|
||||
(NOTE: We have not tested the security of these faucets so please feel free to do your own research or obtain Sepolia ethers from other faucets if needed.)
|
||||
3. Please follow the instructions on the webpages of these faucets.
|
||||
4. A lot of faucets limit the Sepolia ETH to 0.05 ETH/day.
|
||||
5. To obtain more eth, you can do some POW mining. One of those POW faucet is:
|
||||
[https://sepolia-faucet.pk910.de/](https://sepolia-faucet.pk910.de/)
|
||||
6. Enter your Eth account address, accept Captcha and start mining.
|
||||
|
||||

|
||||
|
||||
7. You can see the estimated Sepolia ETH mined per hour. Each session is restricted to a few hours.
|
||||
|
||||

|
||||
|
||||
8. When you exceed the hour limit of the session, then the mining will be stopped.
|
||||
9. Alternatively, stop the mining when mined enough sepolia ether.
|
||||
10. Do not forget to claim your sepolia ether.
|
||||
|
||||

|
||||
|
||||
|
||||
Setting up a hosted node on Sepolia Testnet using Infura
|
||||
---
|
||||
|
||||
(Note: Infura provides a simple straight-forward way of setting up endpoints for interaction with the Ethereum chain and the Waku RLN smart contract without having to run a dedicated Ethereum node. Setting up infura is not mandatory. Operators concerned with the centralized aspect introduced by infura can setup their own node.)
|
||||
|
||||
1. Sign up to infura if you do not have an account already. [https://infura.io/register](https://infura.io/register)
|
||||
|
||||

|
||||
|
||||
2. After registering and verifying the account, create a new project using Ethereum and give it a name.
|
||||
|
||||

|
||||
|
||||
3. After creating the project, you will be presented with a dashboard like follows. Note that your Project Id and secret will be different.
|
||||
|
||||

|
||||
|
||||
4. Select Sepolia network in Endpoints.
|
||||
|
||||

|
||||
|
||||
5. You can find the endpoints for the hosted node using https and wss. The wss endpoint is the relevant one for connecting the waku node to the RLN contract on Sepolia network. Like follows:
|
||||
|
||||

|
||||
|
||||
6. You can change security settings or view usage options as required in the dashboard.
|
||||
7. Congratulations, you are now ready to use the Infura node.
|
||||
@ -1,28 +1,33 @@
|
||||
# Spam-protected chat2 application with on-chain group management
|
||||
|
||||
This document is a tutorial on how to run the chat2 application in the spam-protected mode using the Waku-RLN-Relay protocol and with dynamic/on-chain group management.
|
||||
In the on-chain/dynamic group management, the state of the group members i.e., their identity commitment keys is moderated via a membership smart contract deployed on the Sepolia network which is one of the Ethereum testnets.
|
||||
In the on-chain/dynamic group management, the state of the group members i.e., their identity commitment keys is moderated via a membership smart contract deployed on the Goerli network which is one of the Ethereum testnets.
|
||||
Members can be dynamically added to the group and the group size can grow up to 2^20 members.
|
||||
This differs from the prior test scenarios in which the RLN group was static and the set of members' keys was hardcoded and fixed.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
To complete this tutorial, you will need
|
||||
1. An rln keystore file with credentials to the rln membership smart contract you wish to use. You may obtain this by registering to the smart contract and generating a keystore. It is possible to use go-waku to register into the smart contract:
|
||||
```
|
||||
make
|
||||
./build/waku generate-rln-credentials --eth-account-private-key=<private-key> --eth-contract-address=<0x000...> --eth-client-address=<eth-client-rpc-or-wss-endpoint> --cred-path=./rlnKeystore.json
|
||||
```
|
||||
Once this command is executed, A keystore file will be generated at the path defined in the `--cred-path` flag. You may now use this keystore with wakunode2 or chat2.
|
||||
To complete this tutorial, you will need 1) an account with at least `0.001` ethers on the Goerli testnet and 2) a hosted node on the Goerli testnet.
|
||||
In case you are not familiar with either of these two steps, you may follow the following tutorial to fulfill the [prerequisites of running on-chain spam-protected chat2](./pre-requisites-of-running-on-chain-spam-protected-chat2.md).
|
||||
Note that the required `0.001` ethers correspond to the registration fee,
|
||||
however, you still need to have more funds in your account to cover the cost of the transaction gas fee.
|
||||
|
||||
|
||||
|
||||
## Overview
|
||||
Figure 1 provides an overview of the interaction of the chat2 clients with the test fleets and the membership contract.
|
||||
At a high level, when a chat2 client is run with Waku-RLN-Relay mounted in on-chain mode, the passed in credential will get displayed on the console of your chat2 client.
|
||||
At a high level, when a chat2 client is run with Waku-RLN-Relay mounted in on-chain mode, it creates an RLN credential (i.e., an identity key and an identity commitment key) and
|
||||
sends a transaction to the membership contract to register the corresponding membership identity commitment key.
|
||||
This transaction will also transfer `0.001` Ethers to the contract as a membership fee.
|
||||
This amount plus the transaction fee will be deducted from the supplied Goerli account.
|
||||
Once the transaction is mined and the registration is successful, the registered credential will get displayed on the console of your chat2 client.
|
||||
You may copy the displayed RLN credential and reuse them for the future execution of the chat2 application.
|
||||
Proper instructions in this regard is provided in the following [section](#how-to-persist-and-reuse-rln-credential).
|
||||
If you choose not to reuse the same credential, then for each execution, a new registration will take place and more funds will get deducted from your Goerli account.
|
||||
Under the hood, the chat2 client constantly listens to the membership contract and keeps itself updated with the latest state of the group.
|
||||
|
||||
In the following test setting, the chat2 clients are to be connected to the Waku test fleets as their first hop.
|
||||
The test fleets will act as routers and are also set to run Waku-RLN-Relay over the same pubsub topic and content topic as chat2 clients i.e., the default pubsub topic of `/waku/2/default-waku/proto` and the content topic of `/toy-chat/3/mingde/proto`.
|
||||
The test fleets will act as routers and are also set to run Waku-RLN-Relay over the same pubsub topic and content topic as chat2 clients i.e., the default pubsub topic of `/waku/2/default-waku/proto` and the content topic of `/toy-chat/2/luzhou/proto`.
|
||||
Spam messages published on the said combination of topics will be caught by the test fleet nodes and will not be routed.
|
||||
Note that spam protection does not rely on the presence of the test fleets.
|
||||
In fact, all the chat2 clients are also capable of catching and dropping spam messages if they receive any.
|
||||
@ -43,7 +48,7 @@ git clone https://github.com/waku-org/go-waku
|
||||
cd go-waku
|
||||
```
|
||||
## Build chat2
|
||||
```bash
|
||||
```
|
||||
make chat2
|
||||
```
|
||||
|
||||
@ -51,40 +56,34 @@ make chat2
|
||||
|
||||
Run the following command to set up your chat2 client.
|
||||
|
||||
```bash
|
||||
./build/chat2 --fleet=test \
|
||||
--content-topic=/toy-chat/3/mingde/proto \
|
||||
--rln-relay=true \
|
||||
--rln-relay-dynamic=true \
|
||||
--rln-relay-eth-contract-address=0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 \
|
||||
--rln-relay-cred-path=xxx/xx/rlnKeystore.json \
|
||||
--rln-relay-cred-password=xxxx \
|
||||
--rln-relay-eth-client-address=xxxx
|
||||
```
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/2/luzhou/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-private-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-eth-client-address=xxxx
|
||||
```
|
||||
|
||||
In this command
|
||||
- the `--fleet=test` indicates that the chat2 app gets connected to the test fleets.
|
||||
- the `toy-chat/3/mingde/proto` passed to the `--content-topic` option indicates the content topic on which the chat2 application is going to run.
|
||||
- the `toy-chat/2/luzhou/proto` passed to the `--content-topic` option indicates the content topic on which the chat2 application is going to run.
|
||||
- the `--rln-relay` flag is set to `true` to enable the Waku-RLN-Relay protocol for spam protection.
|
||||
- the `--rln-relay-dynamic` flag is set to `true` to enable the on-chain mode of Waku-RLN-Relay protocol with dynamic group management.
|
||||
- the `--rln-relay-eth-contract-address` option gets the address of the membership contract.
|
||||
The current address of the contract is `0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4`.
|
||||
You may check the state of the contract on the [Sepolia testnet](https://sepolia.etherscan.io/address/0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4).
|
||||
- the `--rln-relay-cred-path` option denotes the path to the keystore file described above
|
||||
- the `--rln-relay-cred-password` option denotes the password to the keystore
|
||||
- the `rln-relay-eth-client-address` is the WebSocket address of the hosted node on the Sepolia testnet.
|
||||
The current address of the contract is `0x4252105670fe33d2947e8ead304969849e64f2a6`.
|
||||
You may check the state of the contract on the [Goerli testnet](https://goerli.etherscan.io/address/0x4252105670fe33d2947e8ead304969849e64f2a6).
|
||||
- the `--rln-relay-eth-account-private-key` option is for your account private key on the Goerli testnet.
|
||||
It is made up of 64 hex characters (not sensitive to the `0x` prefix).
|
||||
- the `--rln-relay-eth-client-address` is the WebSocket address of the hosted node on the Goerli testnet.
|
||||
You need to replace the `xxxx` with the actual node's address.
|
||||
|
||||
For `--rln-relay-eth-client-address`, if you do not know how to obtain it, you may use the following tutorial on the [prerequisites of running on-chain spam-protected chat2](./pre-requisites-of-running-on-chain-spam-protected-chat2.md).
|
||||
For the last three config options i.e., `rln-relay-eth-account-address`, `rln-relay-eth-account-private-key`, and `rln-relay-eth-client-address`, if you do not know how to obtain those, you may use the following tutorial on the [prerequisites of running on-chain spam-protected chat2](./pre-requisites-of-running-on-chain-spam-protected-chat2.md).
|
||||
|
||||
You may set up more than one chat client,
|
||||
using the `--rln-relay-cred-path` flag, specifying in each client a different path to store the credentials.
|
||||
using the `--rln-relay-cred-path` flag, specifying in each client a different path to store the credentials, and using a different `--tcp-port`.
|
||||
|
||||
Once you run the command, you will see the following message:
|
||||
```
|
||||
Setting up dynamic rln...
|
||||
```
|
||||
At this phase, RLN is being setup by obtaining the membership information from the smart contract. Afterwards, messages related to setting up the connections of your chat app will be shown,
|
||||
At this phase, your RLN credential are getting created and a transaction is being sent to the membership smart contract.
|
||||
It will take some time for the transaction to be finalized. Afterwards, messages related to setting up the connections of your chat app will be shown,
|
||||
the content may differ on your screen though:
|
||||
```
|
||||
INFO: Welcome, Anonymous!
|
||||
@ -102,10 +101,10 @@ INFO: RLN config:
|
||||
- Your RLN identity commitment key is: 6c6598126ba10d1b70100893b76d7f8d7343eeb8f5ecfd48371b421c5aa6f012
|
||||
|
||||
INFO: attempting DNS discovery with enrtree://ANTL4SLG2COUILKAPE7EF2BYNL2SHSHVCHLRD5J7ZJLN5R3PRJD2Y@prod.waku.nodes.status.im
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB /dns4/node-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV /dns4/node-01.do-ams3.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE]
|
||||
INFO: Connected to 16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB
|
||||
INFO: Connected to 16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE
|
||||
INFO: Connected to 16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA /dns4/node-01.ac-cn-hongkong- c.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD /dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e]
|
||||
INFO: Connected to 16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA
|
||||
INFO: Connected to 16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e
|
||||
INFO: Connected to 16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD
|
||||
INFO: No store node configured. Choosing one at random...
|
||||
```
|
||||
You will also see some historical messages being fetched, again the content may be different on your end:
|
||||
@ -146,13 +145,9 @@ The reason is that under the hood a zero-knowledge proof is being generated and
|
||||
|
||||
Try to spam the network by violating the message rate limit i.e.,
|
||||
sending more than one message per epoch.
|
||||
Your messages will be routed via test fleets that are running in spam-protected mode over the same content topic i.e., `/toy-chat/3/mingde/proto` as your chat client.
|
||||
Your messages will be routed via test fleets that are running in spam-protected mode over the same content topic i.e., `/toy-chat/2/luzhou/proto` as your chat client.
|
||||
Your spam activity will be detected by them and your message will not reach the rest of the chat clients.
|
||||
You can check this by running a second chat user and verifying that spam messages are not displayed as they are filtered by the test fleets.
|
||||
Furthermore, the chat client will prompt you with the following warning message indicating that the message rate is being violated:
|
||||
```
|
||||
ERROR: message rate violation!
|
||||
```
|
||||
A sample test scenario is illustrated in the [Sample test output section](#sample-test-output).
|
||||
|
||||
Once you are done with the test, make sure you close all the chat2 clients by typing the `/exit` command.
|
||||
@ -161,32 +156,28 @@ Once you are done with the test, make sure you close all the chat2 clients by ty
|
||||
Bye!
|
||||
```
|
||||
|
||||
## How to reuse RLN credential
|
||||
## How to persist and reuse RLN credential
|
||||
|
||||
You may pass the `--rln-relay-cred-path` config option to specify a path to a file for retrieving persisted RLN credentials.
|
||||
If the keystore exists in the path provided, it is used, and will default to the 0th element in the credential array.
|
||||
If the keystore does not exist in the path provided, a new keystore will be created and added to the directory it was supposed to be in.
|
||||
|
||||
You may provide an index to the credential you wish to use by passing the `--rln-relay-cred-index` config option.
|
||||
|
||||
You may provide an index to the membership you wish to use (within the same membership set) by passing the `--rln-relay-membership-group-index` config option.
|
||||
You may pass the `--rln-relay-cred-path` config option to specify a path for 1) persisting RLN credentials and 2) retrieving persisted RLN credentials.
|
||||
RLN credential is persisted in the `rlnCredentials.txt` file under the specified path.
|
||||
If this file does not already exist under the supplied path, then a new credential is generated and persisted in the `rlnCredentials.txt` file.
|
||||
Otherwise, the chat client does not generate a new credential and will use, instead, the persisted RLN credential.
|
||||
|
||||
```bash
|
||||
./build/chat2 --fleet=test \
|
||||
--content-topic=/toy-chat/3/mingde/proto \
|
||||
--rln-relay=true \
|
||||
--rln-relay-dynamic=true \
|
||||
--rln-relay-eth-contract-address=0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 \
|
||||
--rln-relay-eth-client-address=your_sepolia_node \
|
||||
--rln-relay-cred-path=./rlnKeystore.json \
|
||||
--rln-relay-cred-password=your_password \
|
||||
--rln-relay-membership-index=0 \
|
||||
--rln-relay-membership-group-index=0
|
||||
./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-private-key=your_eth_private_key --rln-relay-eth-client-address==your_goerli_node --rln-relay-cred-path:./
|
||||
```
|
||||
|
||||
Note: If you are reusing credentials, you can omit the `--rln-relay-eth-account-private-key` flags
|
||||
|
||||
Therefore, the command to start chat2 would be -
|
||||
|
||||
```bash
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/2/luzhou/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-client-address=your_goerli_node --rln-relay-cred-path=./
|
||||
```
|
||||
|
||||
# Sample test output
|
||||
In this section, a sample test of running two chat clients is provided.
|
||||
Note that the value used for `--rln-relay-eth-client-address` in the following code snippets is junk and not valid.
|
||||
Note that the values used for `--rln-relay-eth-account-private-key`, and `--rln-relay-eth-client-address` in the following code snippets are junk and not valid.
|
||||
|
||||
The two chat clients namely `Alice` and `Bob` are connected to the test fleets.
|
||||
`Alice` sends 4 messages i.e., `message1`, `message2`, `message3`, and `message4`.
|
||||
@ -196,11 +187,9 @@ The test fleets do not relay `message3` further, hence `Bob` never receives it.
|
||||
You can check this fact by looking at `Bob`'s console, where `message3` is missing.
|
||||
|
||||
**Alice**
|
||||
```bash
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/3/mingde/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path=rlnKeystore.json --rln-relay-cred-password=password --rln-relay-eth-client-address=wss://sepolia.infura.io/ws/v3/12345678901234567890123456789012 --nickname=Alice
|
||||
```
|
||||
```
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/2/luzhou/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-private-key=your_eth_private_key --rln-relay-eth-client-address=your_goerli_node --rln-relay-cred-path=./path/to/alice/folder --nickname=Alice
|
||||
|
||||
```
|
||||
Seting up dynamic rln
|
||||
INFO: Welcome, Alice!
|
||||
INFO: type /help to see available commands
|
||||
@ -214,10 +203,10 @@ INFO: RLN config:
|
||||
- Your rln identity commitment key is: bd093cbf14fb933d53f596c33f98b3df83b7e9f7a1906cf4355fac712077cb28
|
||||
|
||||
INFO: attempting DNS discovery with enrtree://ANTL4SLG2COUILKAPE7EF2BYNL2SHSHVCHLRD5J7ZJLN5R3PRJD2Y@prod.waku.nodes.status.im
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB /dns4/node-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV /dns4/node-01.do-ams3.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE]
|
||||
INFO: Connected to 16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB
|
||||
INFO: Connected to 16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE
|
||||
INFO: Connected to 16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA /dns4/node-01.ac-cn-hongkong- c.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD /dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e]
|
||||
INFO: Connected to 16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA
|
||||
INFO: Connected to 16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e
|
||||
INFO: Connected to 16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD
|
||||
INFO: No store node configured. Choosing one at random...
|
||||
|
||||
>> message1
|
||||
@ -246,11 +235,9 @@ INFO RLN Epoch: 165886593
|
||||
```
|
||||
|
||||
**Bob**
|
||||
```bash
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/3/mingde/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path=rlnKeystore.json --rln-relay-cred-index=1 --rln-relay-cred-password=password --rln-relay-eth-client-address=wss://sepolia.infura.io/ws/v3/12345678901234567890123456789012 --nickname=Bob
|
||||
```
|
||||
```
|
||||
./build/chat2 --fleet=test --content-topic=/toy-chat/2/luzhou/proto --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-private-key=your_eth_private_key --rln-relay-eth-client-address=your_goerli_node --rln-relay-cred-path=./path/to/bob/folder --nickname=Bob
|
||||
|
||||
```
|
||||
Seting up dynamic rln
|
||||
INFO: Welcome, Bob!
|
||||
INFO: type /help to see available commands
|
||||
@ -264,13 +251,13 @@ INFO: RLN config:
|
||||
- Your rln identity commitment key is: bd093cbf14fb933d53f596c33f98b3df83b7e9f7a1906cf4355fac712077cb28
|
||||
|
||||
INFO: attempting DNS discovery with enrtree://ANTL4SLG2COUILKAPE7EF2BYNL2SHSHVCHLRD5J7ZJLN5R3PRJD2Y@prod.waku.nodes.status.im
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB /dns4/node-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV /dns4/node-01.do-ams3.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE]
|
||||
INFO: Connected to 16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB
|
||||
INFO: Connected to 16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE
|
||||
INFO: Connected to 16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV
|
||||
INFO: Discovered and connecting to [/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA /dns4/node-01.ac-cn-hongkong- c.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD /dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e]
|
||||
INFO: Connected to 16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA
|
||||
INFO: Connected to 16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e
|
||||
INFO: Connected to 16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD
|
||||
INFO: No store node configured. Choosing one at random...
|
||||
|
||||
[Jul 26 13:05 Alice] message1
|
||||
[Jul 26 13:05 Alice] message2
|
||||
[Jul 26 13:05 Alice] message4
|
||||
```
|
||||
```
|
||||
@ -59,7 +59,7 @@ class MainActivity : AppCompatActivity() {
|
||||
lbl.text = (lbl.text.toString() + ">>> Default pubsub topic: " + defaultPubsubTopic() + "\n");
|
||||
|
||||
try {
|
||||
node.connect("/dns4/node-01.gc-us-central1-a.waku.test.status.im/tcp/30303/p2p/16Uiu2HAmDCp8XJ9z1ev18zuv8NHekAsjNyezAvmMfFEJkiharitG")
|
||||
node.connect("/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS")
|
||||
lbl.text = (lbl.text.toString() + ">>> Connected to Peer" + "\n")
|
||||
|
||||
node.peers().forEach {
|
||||
|
||||
@ -22,3 +22,12 @@ fun ContentTopic(applicationName: String, applicationVersion: Long, contentTopic
|
||||
return Gowaku.contentTopic(applicationName, applicationVersion, contentTopicName, encoding)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pubsub topic string
|
||||
* @param name
|
||||
* @param encoding
|
||||
* @return Pubsub topic string according to RFC 23
|
||||
*/
|
||||
fun PubsubTopic(name: String, encoding: String): String {
|
||||
return Gowaku.pubsubTopic(name, encoding)
|
||||
}
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
.PHONY: all build
|
||||
|
||||
build:
|
||||
go build -o build/basic_light_client .
|
||||
|
||||
all: build
|
||||
@ -1,35 +0,0 @@
|
||||
# Using the `basic_light_client` application
|
||||
|
||||
## Background
|
||||
|
||||
The `basic_light_client` application is a basic example app that demonstrates how to send/receive messages using Waku Filter and Lightpush.
|
||||
|
||||
There are 2 ways of running the example.:
|
||||
1. To work with the public Waku network in which case it uses the autosharding feature.This is the default way to run this.
|
||||
2. To work with a custom Waku network which using static sharding. In this case a clusterID has to be specified.
|
||||
|
||||
## Preparation
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
## Basic application usage
|
||||
|
||||
To start the `basic_light_client` application run the following from the project directory
|
||||
|
||||
```
|
||||
./build/basic_light_client --maddr=<filterNode>
|
||||
```
|
||||
|
||||
The app will send a "Hello world!" through the lightpush protocol and display it on the terminal as soon as it receives the message.
|
||||
|
||||
In order to run it with you own static sharded network, then run it as below
|
||||
|
||||
```
|
||||
./build/basic_light_client --maddr=<filterNode> --cluster-id=<value of cluster-id> --shard=<shard number>
|
||||
```
|
||||
e.g: ./build/basic_light_client --maddr="/ip4/0.0.0.0/tcp/30304/p2p/16Uiu2HAmBu5zRFzBGAzzMAuGWhaxN2EwcbW7CzibELQELzisf192" --cluster-id=2 --shard=1 // If you want to run with clusterID 2 and shard as 1
|
||||
|
||||
Cluster-id is a unique identifier for your own network and shard number is a segment/shard identifier of your network.
|
||||
|
||||
Note that clusterID's 1 & 16 are reserved for the public Waku Network and Status repectively.
|
||||
@ -1,168 +0,0 @@
|
||||
module basic2
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.11
|
||||
|
||||
replace github.com/waku-org/go-waku => ../..
|
||||
|
||||
replace github.com/ethereum/go-ethereum v1.10.26 => github.com/status-im/go-ethereum v1.10.25-status.15
|
||||
|
||||
replace github.com/libp2p/go-libp2p-pubsub v0.13.1 => github.com/waku-org/go-libp2p-pubsub v0.13.1-gowaku
|
||||
|
||||
require (
|
||||
github.com/ethereum/go-ethereum v1.16.3
|
||||
github.com/libp2p/go-libp2p v0.39.1
|
||||
github.com/multiformats/go-multiaddr v0.14.0
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
github.com/waku-org/go-waku v0.2.3-0.20221109195301-b2a5a68d28ba
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/protobuf v1.36.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/avast/retry-go/v4 v4.5.1 // indirect
|
||||
github.com/beevik/ntp v0.3.0 // indirect
|
||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.20.0 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/consensys/gnark-crypto v0.18.0 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
||||
github.com/cruxic/go-hmac-drbg v0.0.0-20170206035330-84c46983886d // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/elastic/gosigar v0.14.3 // indirect
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
|
||||
github.com/ethereum/go-verkle v0.2.2 // indirect
|
||||
github.com/flynn/noise v1.1.0 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/holiman/uint256 v1.3.2 // indirect
|
||||
github.com/huin/goupnp v1.3.0 // indirect
|
||||
github.com/ipfs/go-cid v0.5.0 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/koron/go-ssdp v0.0.5 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/libp2p/go-flow-metrics v0.2.0 // indirect
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
|
||||
github.com/libp2p/go-libp2p-pubsub v0.13.1 // indirect
|
||||
github.com/libp2p/go-msgio v0.3.0 // indirect
|
||||
github.com/libp2p/go-nat v0.2.0 // indirect
|
||||
github.com/libp2p/go-netroute v0.2.2 // indirect
|
||||
github.com/libp2p/go-reuseport v0.4.0 // indirect
|
||||
github.com/libp2p/go-yamux/v4 v4.0.2 // indirect
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.63 // indirect
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||
github.com/multiformats/go-multicodec v0.9.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-multistream v0.6.0 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pion/datachannel v1.5.10 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.12 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.4 // indirect
|
||||
github.com/pion/ice/v2 v2.3.37 // indirect
|
||||
github.com/pion/ice/v4 v4.0.6 // indirect
|
||||
github.com/pion/interceptor v0.1.37 // indirect
|
||||
github.com/pion/logging v0.2.3 // indirect
|
||||
github.com/pion/mdns v0.0.12 // indirect
|
||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.15 // indirect
|
||||
github.com/pion/rtp v1.8.11 // indirect
|
||||
github.com/pion/sctp v1.8.35 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.10 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.4 // indirect
|
||||
github.com/pion/stun v0.6.1 // indirect
|
||||
github.com/pion/stun/v2 v2.0.0 // indirect
|
||||
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||
github.com/pion/transport/v2 v2.2.10 // indirect
|
||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||
github.com/pion/turn/v2 v2.1.6 // indirect
|
||||
github.com/pion/turn/v4 v4.0.0 // indirect
|
||||
github.com/pion/webrtc/v4 v4.0.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.49.0 // indirect
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
|
||||
github.com/raulk/go-watchdog v1.3.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/supranational/blst v0.3.14 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/waku-org/go-discover v0.0.0-20251003191045-8ee308fe7971 // indirect
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0 // indirect
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b // indirect
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 // indirect
|
||||
github.com/wk8/go-ordered-map v1.0.0 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
go.uber.org/dig v1.18.0 // indirect
|
||||
go.uber.org/fx v1.23.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
@ -1,781 +0,0 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
|
||||
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh7o=
|
||||
github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc=
|
||||
github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw=
|
||||
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
|
||||
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
|
||||
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
||||
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
|
||||
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
|
||||
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||
github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw=
|
||||
github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo=
|
||||
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
||||
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
|
||||
github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0=
|
||||
github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
|
||||
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI=
|
||||
github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
|
||||
github.com/cruxic/go-hmac-drbg v0.0.0-20170206035330-84c46983886d h1:bE1UyBQ5aE6FjhNY4lbPtMqh7VDldoVkvZMtFEbd+CE=
|
||||
github.com/cruxic/go-hmac-drbg v0.0.0-20170206035330-84c46983886d/go.mod h1:HAe1wsCrwH2uFnFaCC2vlcyEohnxs8KeShAFqGIHvmM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
|
||||
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
||||
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
|
||||
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0=
|
||||
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
|
||||
github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
|
||||
github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
|
||||
github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
|
||||
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
|
||||
github.com/ethereum/go-ethereum v1.16.3 h1:nDoBSrmsrPbrDIVLTkDQCy1U9KdHN+F2PzvMbDoS42Q=
|
||||
github.com/ethereum/go-ethereum v1.16.3/go.mod h1:Lrsc6bt9Gm9RyvhfFK53vboCia8kpF9nv+2Ukntnl+8=
|
||||
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
|
||||
github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
|
||||
github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY=
|
||||
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
|
||||
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-migrate/migrate/v4 v4.15.2 h1:vU+M05vs6jWHKDdmE1Ecwj0BznygFc4QsdRe2E/L7kc=
|
||||
github.com/golang-migrate/migrate/v4 v4.15.2/go.mod h1:f2toGLkYqD3JH+Todi4aZ2ZdbeUNx4sIwiOK96rE9Lw=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 h1:wlQI2cYY0BsWmmPPAnxfQ8SDW0S3Jasn+4B8kXFxprg=
|
||||
github.com/google/pprof v0.0.0-20250202011525-fc3143867406/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
|
||||
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
|
||||
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=
|
||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
|
||||
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
|
||||
github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
|
||||
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
|
||||
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
|
||||
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/koron/go-ssdp v0.0.5 h1:E1iSMxIs4WqxTbIBLtmNBeOOC+1sCIXQeqTWVnpmwhk=
|
||||
github.com/koron/go-ssdp v0.0.5/go.mod h1:Qm59B7hpKpDqfyRNWRNr00jGwLdXjDyZh6y7rH6VS0w=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
|
||||
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
||||
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||
github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
|
||||
github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
|
||||
github.com/libp2p/go-libp2p v0.39.1 h1:1Ur6rPCf3GR+g8jkrnaQaM0ha2IGespsnNlCqJLLALE=
|
||||
github.com/libp2p/go-libp2p v0.39.1/go.mod h1:3zicI8Lp7Isun+Afo/JOACUbbJqqR2owK6RQWFsVAbI=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
|
||||
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
|
||||
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
|
||||
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
|
||||
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
|
||||
github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
|
||||
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
|
||||
github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
|
||||
github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
|
||||
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
|
||||
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
|
||||
github.com/libp2p/go-yamux/v4 v4.0.2 h1:nrLh89LN/LEiqcFiqdKDRHjGstN300C1269K/EX0CPU=
|
||||
github.com/libp2p/go-yamux/v4 v4.0.2/go.mod h1:C808cCRgOs1iBwY4S71T5oxgMxgLmqUw56qh4AeBW2o=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
|
||||
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
|
||||
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
|
||||
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
|
||||
github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU=
|
||||
github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4=
|
||||
github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
|
||||
github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
|
||||
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
|
||||
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
|
||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA=
|
||||
github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg=
|
||||
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
|
||||
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
|
||||
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
|
||||
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
|
||||
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
|
||||
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
|
||||
github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
|
||||
github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
|
||||
github.com/pion/ice/v2 v2.3.37 h1:ObIdaNDu1rCo7hObhs34YSBcO7fjslJMZV0ux+uZWh0=
|
||||
github.com/pion/ice/v2 v2.3.37/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ=
|
||||
github.com/pion/ice/v4 v4.0.6 h1:jmM9HwI9lfetQV/39uD0nY4y++XZNPhvzIPCb8EwxUM=
|
||||
github.com/pion/ice/v4 v4.0.6/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
||||
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||
github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8=
|
||||
github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk=
|
||||
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||
github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
|
||||
github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
||||
github.com/pion/sctp v1.8.35 h1:qwtKvNK1Wc5tHMIYgTDJhfZk7vATGVHhXbUDfHbYwzA=
|
||||
github.com/pion/sctp v1.8.35/go.mod h1:EcXP8zCYVTRy3W9xtOF7wJm1L1aXfKRQzaM33SjQlzg=
|
||||
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
|
||||
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
|
||||
github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
|
||||
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
||||
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
||||
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
|
||||
github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ=
|
||||
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
|
||||
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
|
||||
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
|
||||
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
|
||||
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
|
||||
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
|
||||
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
|
||||
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
|
||||
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
|
||||
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
|
||||
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
|
||||
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
|
||||
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
|
||||
github.com/pion/webrtc/v4 v4.0.8 h1:T1ZmnT9qxIJIt4d8XoiMOBrTClGHDDXNg9e/fh018Qc=
|
||||
github.com/pion/webrtc/v4 v4.0.8/go.mod h1:HHBeUVBAC+j4ZFnYhovEFStF02Arb1EyD4G7e7HBTJw=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
|
||||
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
|
||||
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
|
||||
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo=
|
||||
github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/waku-org/go-discover v0.0.0-20251003191045-8ee308fe7971 h1:BNw9UkCVftI0l0QWm5ofpM5HaLfRuv77Fcea4byk6wk=
|
||||
github.com/waku-org/go-discover v0.0.0-20251003191045-8ee308fe7971/go.mod h1:oVHZeHiB/OJpc0k4r+Iq+5bJXvOV3Mpz1gPQh8Vswps=
|
||||
github.com/waku-org/go-libp2p-pubsub v0.13.1-gowaku h1:ovXh1m76i0yPWXt95Z9ZRyEk0+WKSuPt5e4IddgwUrY=
|
||||
github.com/waku-org/go-libp2p-pubsub v0.13.1-gowaku/go.mod h1:MKPU5vMI8RRFyTP0HfdsF9cLmL1nHAeJm44AxJGJx44=
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0 h1:R4YYx2QamhBRl/moIxkDCNW+OP7AHbyWLBygDc/xIMo=
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0/go.mod h1:EhZP9fee0DYjKH/IOQvoNSy1tSHp2iZadsHGphcAJgY=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59 h1:jisj+OCI6QydLtFq3Pyhu49wl9ytPN7oAHjMfepHDrA=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59/go.mod h1:1PdBdPzyTaKt3VnpAHk3zj+r9dXPFOr3IHZP9nFle6E=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b h1:KgZVhsLkxsj5gb/FfndSCQu6VYwALrCOgYI3poR95yE=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 h1:Sd7QD/1Yo2o2M1MY49F8Zr4KNBPUEK5cz5HoXQVJbrs=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 h1:4HSdWMFMufpRo3ECTX6BrvA+VzKhXZf7mS0rTa5cCWU=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
|
||||
github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8=
|
||||
github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk=
|
||||
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
|
||||
go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
|
||||
go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
|
||||
go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc=
|
||||
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
@ -1,271 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/payload"
|
||||
wps "github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var log = utils.Logger().Named("basic-light-client")
|
||||
|
||||
var ClusterID = altsrc.NewUintFlag(&cli.UintFlag{
|
||||
Name: "cluster-id",
|
||||
Value: 1,
|
||||
Usage: "Cluster id that the client is interested in connecting to.",
|
||||
Destination: &clusterID,
|
||||
})
|
||||
|
||||
var Shard = altsrc.NewUintFlag(&cli.UintFlag{
|
||||
Name: "shard",
|
||||
Value: 0,
|
||||
Usage: "shard that the node is interested in publishing/receiving from.",
|
||||
Destination: &shard,
|
||||
})
|
||||
|
||||
var StaticNode = altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "maddr",
|
||||
Usage: "multiaddress of static node to connect to.",
|
||||
Destination: &multiaddress,
|
||||
Required: true,
|
||||
})
|
||||
|
||||
var clusterID, shard uint
|
||||
var pubsubTopicStr string
|
||||
var multiaddress string
|
||||
|
||||
func main() {
|
||||
|
||||
cliFlags := []cli.Flag{
|
||||
ClusterID,
|
||||
Shard,
|
||||
StaticNode,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "basic-light-client-example",
|
||||
Flags: cliFlags,
|
||||
Action: func(c *cli.Context) error {
|
||||
err := Execute()
|
||||
if err != nil {
|
||||
utils.Logger().Error("failure while executing wakunode", zap.Error(err))
|
||||
switch e := err.(type) {
|
||||
case cli.ExitCoder:
|
||||
return e
|
||||
case error:
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
|
||||
var cTopic, err = protocol.NewContentTopic("basic-light-client", "1", "test", "proto")
|
||||
if err != nil {
|
||||
return errors.New("invalid contentTopic")
|
||||
}
|
||||
contentTopic := cTopic.String()
|
||||
hostAddr, _ := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
|
||||
key, err := randomHex(32)
|
||||
if err != nil {
|
||||
log.Error("Could not generate random key", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
prvKey, err := crypto.HexToECDSA(key)
|
||||
if err != nil {
|
||||
log.Error("Could not convert hex into ecdsa key", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
lightNode, err := node.New(
|
||||
node.WithPrivateKey(prvKey),
|
||||
node.WithHostAddress(hostAddr),
|
||||
node.WithWakuFilterLightNode(),
|
||||
node.WithClusterID(uint16(clusterID)),
|
||||
//node.WithLogLevel(zapcore.DebugLevel),
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("Error creating wakunode", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
err = lightNode.Start(ctx)
|
||||
if err != nil {
|
||||
log.Error("Error starting wakunode", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
//Populate pubsubTopic if shard is specified. Otherwise it is derived via autosharing algorithm
|
||||
if shard != 0 {
|
||||
pubsubTopic := protocol.NewStaticShardingPubsubTopic(uint16(clusterID), uint16(shard))
|
||||
pubsubTopicStr = pubsubTopic.String()
|
||||
}
|
||||
|
||||
maddr, err := multiaddr.NewMultiaddr(multiaddress)
|
||||
if err != nil {
|
||||
log.Info("Error decoding multiaddr ", zap.Error(err))
|
||||
}
|
||||
peerID, err := lightNode.AddPeer([]multiaddr.Multiaddr{maddr}, wps.Static,
|
||||
[]string{pubsubTopicStr}, filter.FilterSubscribeID_v20beta1, lightpush.LightPushID_v20beta1)
|
||||
if err != nil {
|
||||
log.Info("Error adding filter peer on light node ", zap.Error(err))
|
||||
}
|
||||
|
||||
useFilterAndLightPush(lightNode, contentTopic, pubsubTopicStr, peerID)
|
||||
|
||||
// shut the node down
|
||||
lightNode.Stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func useFilterAndLightPush(lightNode *node.WakuNode, contentTopic string, pubsubTopic string, filterNode peer.ID) {
|
||||
|
||||
// Send FilterRequest from light node to full node
|
||||
cf := protocol.ContentFilter{
|
||||
PubsubTopic: pubsubTopic,
|
||||
ContentTopics: protocol.NewContentTopicSet(contentTopic),
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
log.Info("Subscribing to peer ", zap.String("peerId", filterNode.String()))
|
||||
theFilter, err := lightNode.FilterLightnode().Subscribe(context.Background(), cf, filter.WithPeer(filterNode))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for env := range theFilter[0].C { //Safely picking first subscriptions since only 1 contentTopic is subscribed
|
||||
log.Info("Light node received msg ", zap.String("message", string(env.Message().Payload)))
|
||||
}
|
||||
log.Info("Message channel closed!")
|
||||
}()
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
msg := &pb.WakuMessage{ContentTopic: contentTopic, Version: proto.Uint32(1), Timestamp: proto.Int64(time.Now().Unix()), Payload: []byte("Hello World!")}
|
||||
hash, err := lightNode.Lightpush().Publish(context.Background(), msg, lightpush.WithPeer(filterNode), lightpush.WithPubSubTopic(pubsubTopic))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Info("published msg via lightpush with hash:", zap.Stringer("hash", hash))
|
||||
|
||||
log.Info("Done sending msgs.......")
|
||||
|
||||
log.Info("Press Ctrl+C to exit safely")
|
||||
|
||||
// Wait for a SIGINT or SIGTERM signal
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-ch
|
||||
fmt.Println("\n\n\nReceived signal, shutting down...")
|
||||
|
||||
log.Info("UnSubscribing to peer ", zap.String("filterNode", filterNode.String()))
|
||||
|
||||
result, err := lightNode.FilterLightnode().Unsubscribe(context.Background(), cf, filter.WithPeer(filterNode))
|
||||
if err != nil {
|
||||
log.Error("failed to unsubscribe due to ", zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
for _, err := range result.Errors() {
|
||||
if err.Err != nil {
|
||||
log.Error("failed to unsubscribe due to res err", zap.Error(err.Err))
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func randomHex(n int) (string, error) {
|
||||
bytes := make([]byte, n)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
func write(ctx context.Context, wakuNode *node.WakuNode, contentTopic string, msgContent string) {
|
||||
var version uint32 = 0
|
||||
|
||||
p := new(payload.Payload)
|
||||
p.Data = []byte(wakuNode.ID() + ": " + msgContent)
|
||||
p.Key = &payload.KeyInfo{Kind: payload.None}
|
||||
|
||||
payload, err := p.Encode(version)
|
||||
if err != nil {
|
||||
log.Error("Error encoding the payload", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
msg := &pb.WakuMessage{
|
||||
Payload: payload,
|
||||
Version: proto.Uint32(version),
|
||||
ContentTopic: contentTopic,
|
||||
Timestamp: utils.GetUnixEpoch(wakuNode.Timesource()),
|
||||
}
|
||||
|
||||
_, err = wakuNode.Relay().Publish(ctx, msg, relay.WithPubSubTopic(pubsubTopicStr))
|
||||
if err != nil {
|
||||
log.Error("Error sending a message", zap.Error(err))
|
||||
}
|
||||
log.Info("Published msg,", zap.String("data", string(msg.Payload)))
|
||||
}
|
||||
|
||||
func writeLoop(ctx context.Context, wakuNode *node.WakuNode, contentTopic string) {
|
||||
for {
|
||||
time.Sleep(2 * time.Second)
|
||||
write(ctx, wakuNode, contentTopic, "Hello world!")
|
||||
}
|
||||
}
|
||||
|
||||
func readLoop(ctx context.Context, wakuNode *node.WakuNode, contentTopic string) {
|
||||
sub, err := wakuNode.Relay().Subscribe(ctx, protocol.NewContentFilter(pubsubTopicStr, contentTopic))
|
||||
if err != nil {
|
||||
log.Error("Could not subscribe", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
for envelope := range sub[0].Ch {
|
||||
if envelope.Message().ContentTopic != contentTopic {
|
||||
continue
|
||||
}
|
||||
|
||||
payload, err := payload.DecodePayload(envelope.Message(), &payload.KeyInfo{Kind: payload.None})
|
||||
if err != nil {
|
||||
log.Error("Error decoding payload", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info("Received msg, ", zap.String("data", string(payload.Data)))
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
.PHONY: all build
|
||||
|
||||
build:
|
||||
go build -o build/basic_relay .
|
||||
|
||||
all: build
|
||||
@ -1,35 +0,0 @@
|
||||
# Using the `basic_relay` application
|
||||
|
||||
## Background
|
||||
|
||||
The `basic_relay` application is a basic example app that demonstrates how to subscribe to and publish messages using Waku relay.
|
||||
|
||||
There are 2 ways of running the example.:
|
||||
1. To work with the public Waku network in which case it uses the autosharding feature.This is the default way to run this.
|
||||
2. To work with a custom Waku network which using static sharding. In this case a clusterID has to be specified.
|
||||
|
||||
## Preparation
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
## Basic application usage
|
||||
|
||||
To start the `basic_relay` application run the following from the project directory
|
||||
|
||||
```
|
||||
./build/basic_relay
|
||||
```
|
||||
|
||||
The app will send a "Hello world!" through the wakurelay protocol every 2 seconds and display it on the terminal as soon as it receives the message.
|
||||
|
||||
In order to run it with you own static sharded network, then run it as below
|
||||
|
||||
```
|
||||
./build/basic_relay --cluster-id=<value of cluster-id> --shard=<shard number>
|
||||
```
|
||||
e.g: ./build/basic_relay --cluster-id=2 --shard=1 // If you want to run with clusterID 2 and shard as 1
|
||||
|
||||
Cluster-id is a unique identifier for your own network and shard number is a segment/shard identifier of your network.
|
||||
|
||||
Note that clusterID's 1 & 16 are reserved for the public Waku Network and Status repectively.
|
||||
2
examples/basic-relay/build/.gitignore
vendored
2
examples/basic-relay/build/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
||||
@ -1,168 +0,0 @@
|
||||
module basic2
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.11
|
||||
|
||||
replace github.com/waku-org/go-waku => ../..
|
||||
|
||||
replace github.com/ethereum/go-ethereum v1.10.26 => github.com/status-im/go-ethereum v1.10.25-status.15
|
||||
|
||||
replace github.com/libp2p/go-libp2p-pubsub v0.13.1 => github.com/waku-org/go-libp2p-pubsub v0.13.1-gowaku
|
||||
|
||||
require (
|
||||
github.com/ethereum/go-ethereum v1.16.3
|
||||
github.com/multiformats/go-multiaddr v0.14.0
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
github.com/waku-org/go-waku v0.2.3-0.20221109195301-b2a5a68d28ba
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/protobuf v1.36.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/avast/retry-go/v4 v4.5.1 // indirect
|
||||
github.com/beevik/ntp v0.3.0 // indirect
|
||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.20.0 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/consensys/gnark-crypto v0.18.0 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
||||
github.com/cruxic/go-hmac-drbg v0.0.0-20170206035330-84c46983886d // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/elastic/gosigar v0.14.3 // indirect
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
|
||||
github.com/ethereum/go-verkle v0.2.2 // indirect
|
||||
github.com/flynn/noise v1.1.0 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/holiman/uint256 v1.3.2 // indirect
|
||||
github.com/huin/goupnp v1.3.0 // indirect
|
||||
github.com/ipfs/go-cid v0.5.0 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/koron/go-ssdp v0.0.5 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/libp2p/go-flow-metrics v0.2.0 // indirect
|
||||
github.com/libp2p/go-libp2p v0.39.1 // indirect
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
|
||||
github.com/libp2p/go-libp2p-pubsub v0.13.1 // indirect
|
||||
github.com/libp2p/go-msgio v0.3.0 // indirect
|
||||
github.com/libp2p/go-nat v0.2.0 // indirect
|
||||
github.com/libp2p/go-netroute v0.2.2 // indirect
|
||||
github.com/libp2p/go-reuseport v0.4.0 // indirect
|
||||
github.com/libp2p/go-yamux/v4 v4.0.2 // indirect
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.63 // indirect
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||
github.com/multiformats/go-multicodec v0.9.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-multistream v0.6.0 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pion/datachannel v1.5.10 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.12 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.4 // indirect
|
||||
github.com/pion/ice/v2 v2.3.37 // indirect
|
||||
github.com/pion/ice/v4 v4.0.6 // indirect
|
||||
github.com/pion/interceptor v0.1.37 // indirect
|
||||
github.com/pion/logging v0.2.3 // indirect
|
||||
github.com/pion/mdns v0.0.12 // indirect
|
||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.15 // indirect
|
||||
github.com/pion/rtp v1.8.11 // indirect
|
||||
github.com/pion/sctp v1.8.35 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.10 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.4 // indirect
|
||||
github.com/pion/stun v0.6.1 // indirect
|
||||
github.com/pion/stun/v2 v2.0.0 // indirect
|
||||
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||
github.com/pion/transport/v2 v2.2.10 // indirect
|
||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||
github.com/pion/turn/v2 v2.1.6 // indirect
|
||||
github.com/pion/turn/v4 v4.0.0 // indirect
|
||||
github.com/pion/webrtc/v4 v4.0.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.49.0 // indirect
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
|
||||
github.com/raulk/go-watchdog v1.3.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/supranational/blst v0.3.14 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/waku-org/go-discover v0.0.0-20251003191045-8ee308fe7971 // indirect
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0 // indirect
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b // indirect
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 // indirect
|
||||
github.com/wk8/go-ordered-map v1.0.0 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
go.uber.org/dig v1.18.0 // indirect
|
||||
go.uber.org/fx v1.23.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user