feat: make rln optional

This commit is contained in:
Richard Ramos 2022-08-12 08:44:13 -04:00
parent e5b6053f12
commit 4589b6c31c
17 changed files with 763 additions and 643 deletions

View File

@ -38,12 +38,18 @@ BUILD_FLAGS ?= $(shell echo "-ldflags='\
-X github.com/status-im/go-waku/waku/v2/node.GitCommit=$(GIT_COMMIT) \
-X github.com/status-im/go-waku/waku/v2/node.Version=$(VERSION)'")
# control rln code compilation
ifeq ($(RLN), true)
BUILD_TAGS := gowaku_rln
endif
all: build
deps: lint-install
build:
${GOBIN} build $(BUILD_FLAGS) -o build/waku waku.go
${GOBIN} build -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o build/waku
vendor:
${GOBIN} mod tidy
@ -105,6 +111,7 @@ static-library:
@echo "Building static library..."
${GOBIN} build \
-buildmode=c-archive \
-tags="${BUILD_TAGS}" \
-o ./build/lib/libgowaku.a \
./library/
@echo "Static library built:"
@ -114,6 +121,7 @@ dynamic-library:
@echo "Building shared library..."
$(GOBIN_SHARED_LIB_CFLAGS) $(GOBIN_SHARED_LIB_CGO_LDFLAGS) ${GOBIN} build \
-buildmode=c-shared \
-tags="${BUILD_TAGS}" \
-o ./build/lib/libgowaku.$(GOBIN_SHARED_LIB_EXT) \
./library/
ifeq ($(detected_OS),Linux)
@ -128,14 +136,14 @@ endif
mobile-android:
gomobile init && \
go get -d golang.org/x/mobile/cmd/gomobile && \
gomobile bind -v -target=android -ldflags="-s -w" $(BUILD_FLAGS) -o ./build/lib/gowaku.aar ./mobile
gomobile bind -v -target=android -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 && \
go get -d golang.org/x/mobile/cmd/gomobile && \
gomobile bind -target=ios -ldflags="-s -w" -o ./build/lib/Gowaku.xcframework ./mobile
gomobile bind -target=ios -ldflags="-s -w" -tags="${BUILD_TAGS}" $(BUILD_FLAGS) -o ./build/lib/Gowaku.xcframework ./mobile
@echo "IOS library built:"
@ls -la ./build/lib/*.xcframework
@ -158,6 +166,7 @@ start-ganache:
stop-ganache:
docker stop ganache-cli
test-onchain: BUILD_TAGS += include_onchain_tests
test-onchain:
${GOBIN} test -v -count 1 -tags="include_onchain_tests" github.com/status-im/go-waku/waku/v2/protocol/rln
${GOBIN} test -v -count 1 -tags="${BUILD_TAGS}" github.com/status-im/go-waku/waku/v2/protocol/rln

2
go.mod
View File

@ -40,7 +40,7 @@ require (
require (
github.com/flynn/noise v1.0.0
github.com/gorilla/mux v1.8.0
github.com/status-im/go-rln v0.0.8
github.com/status-im/go-rln v0.0.9
golang.org/x/text v0.3.7
)

4
go.sum
View File

@ -1693,8 +1693,8 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/go-discover v0.0.0-20220406135310-85a2ce36f63e h1:fDm8hqKGFy8LMNV8zedT3W+QYVPVDfb0F9Fr7fVf9rQ=
github.com/status-im/go-discover v0.0.0-20220406135310-85a2ce36f63e/go.mod h1:u1s0ACIlweIjmJrgXyljRPSOflZLaS6ezb044+92W3c=
github.com/status-im/go-rln v0.0.8 h1:OD27bZFUFhfd9ZkE715wEozv5DCueE0i9Z9a0qwCzog=
github.com/status-im/go-rln v0.0.8/go.mod h1:t8Bf4nNAuQh9VlEiz/rgFVtEz7sjEfcd62MIuEnZn8U=
github.com/status-im/go-rln v0.0.9 h1:qDmFJoFS/1PGNDB0pEjlRDRNZUpIFBAde2f3fIixCbA=
github.com/status-im/go-rln v0.0.9/go.mod h1:t8Bf4nNAuQh9VlEiz/rgFVtEz7sjEfcd62MIuEnZn8U=
github.com/status-im/go-waku-rendezvous v0.0.0-20211018070416-a93f3b70c432 h1:cbNFU38iimo9fY4B7CdF/fvIF6tNPJIZjBbpfmW2EY4=
github.com/status-im/go-waku-rendezvous v0.0.0-20211018070416-a93f3b70c432/go.mod h1:A8t3i0CUGtXCA0aiLsP7iyikmk/KaD/2XVvNJqGCU20=
github.com/status-im/go-watchdog v1.2.0-ios-nolibproc h1:BJwZEF7OVKaXc2zErBUAolFSGzwrTBbWnN8e/6MER5E=

74
waku.go
View File

@ -12,8 +12,7 @@ import (
var options waku.Options
func main() {
app := &cli.App{
Flags: []cli.Flag{
cliFlags := []cli.Flag{
&cli.IntFlag{
Name: "tcp-port",
Aliases: []string{"port", "p"},
@ -278,69 +277,6 @@ func main() {
Usage: "Multiaddr of a peer that supports lightpush protocol. Option may be repeated",
Destination: &options.LightPush.Nodes,
},
&cli.BoolFlag{
Name: "rln-relay",
Value: false,
Usage: "Enable spam protection through rln-relay",
Destination: &options.RLNRelay.Enable,
},
&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",
Usage: "Enable waku-rln-relay with on-chain dynamic group management",
Destination: &options.RLNRelay.Dynamic,
},
&cli.StringFlag{
Name: "rln-relay-id",
Usage: "Rln relay identity secret key as a Hex string",
Destination: &options.RLNRelay.IDKey,
},
&cli.StringFlag{
Name: "rln-relay-id-commitment",
Usage: "Rln relay identity commitment key as a Hex string",
Destination: &options.RLNRelay.IDCommitment,
},
&cli.StringFlag{
Name: "rln-relay-membership-credentials-file",
Usage: "RLN relay membership credentials file",
Value: "rlnCredentials.txt",
Destination: &options.RLNRelay.CredentialsFile,
},
// TODO: this is a good candidate option for subcommands
// TODO: consider accepting a private key file and passwd
&cli.StringFlag{
Name: "eth-private-key",
Usage: "Ethereum Goerli testnet account private key used for registering in member contract",
Destination: &options.RLNRelay.ETHPrivateKey,
},
&cli.StringFlag{
Name: "eth-client-address",
Usage: "Ethereum testnet client address",
Value: "ws://localhost:8545",
Destination: &options.RLNRelay.ETHClientAddress,
},
&cli.StringFlag{
Name: "eth-mem-contract-address",
Usage: "Address of membership contract on an Ethereum testnet",
Destination: &options.RLNRelay.MembershipContractAddress,
},
&cli.BoolFlag{
Name: "discv5-discovery",
Usage: "Enable discovering nodes via Node Discovery v5",
@ -484,7 +420,13 @@ func main() {
Usage: "Enable access to REST HTTP Private API",
Destination: &options.RESTServer.Private,
},
},
}
rlnFlags := rlnFlags()
cliFlags = append(cliFlags, rlnFlags...)
app := &cli.App{
Flags: cliFlags,
Action: func(c *cli.Context) error {
// for go-libp2p loggers
lvl, err := logging.LevelFromString(options.LogLevel)

View File

@ -19,7 +19,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
dssql "github.com/ipfs/go-ds-sql"
"github.com/status-im/go-rln/rln"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
@ -256,41 +255,7 @@ func Execute(options Options) {
nodeOpts = append(nodeOpts, node.WithDiscoveryV5(options.DiscV5.Port, bootnodes, options.DiscV5.AutoUpdate, pubsub.WithDiscoveryOpts(discovery.Limit(45), discovery.TTL(time.Duration(20)*time.Second))))
}
loadedCredentialsFromFile := false
if options.RLNRelay.Enable {
if !options.Relay.Enable {
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
}
if !options.RLNRelay.Dynamic {
nodeOpts = append(nodeOpts, node.WithStaticRLNRelay(options.RLNRelay.PubsubTopic, options.RLNRelay.ContentTopic, rln.MembershipIndex(options.RLNRelay.MembershipIndex), nil))
} else {
var ethPrivKey *ecdsa.PrivateKey
if options.RLNRelay.ETHPrivateKey != "" {
k, err := crypto.ToECDSA(common.FromHex(options.RLNRelay.ETHPrivateKey))
failOnErr(err, "Invalid private key")
ethPrivKey = k
}
loaded, idKey, idCommitment, membershipIndex, err := getMembershipCredentials(options)
failOnErr(err, "Invalid membership credentials")
loadedCredentialsFromFile = loaded
nodeOpts = append(nodeOpts, node.WithDynamicRLNRelay(
options.RLNRelay.PubsubTopic,
options.RLNRelay.ContentTopic,
membershipIndex,
idKey,
idCommitment,
nil,
options.RLNRelay.ETHClientAddress,
ethPrivKey,
common.HexToAddress(options.RLNRelay.MembershipContractAddress),
))
}
}
checkForRLN(options, &nodeOpts)
wakuNode, err := node.New(ctx, nodeOpts...)
@ -348,10 +313,7 @@ func Execute(options Options) {
}
}
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile {
err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), options.RLNRelay.CredentialsFile, []byte(options.KeyPasswd), options.Overwrite)
failOnErr(err, "Could not write membership credentials file")
}
onStartRLN(wakuNode, options)
var rpcServer *rpc.WakuRpc
if options.RPCServer.Enable {

14
waku/node_no_rln.go Normal file
View File

@ -0,0 +1,14 @@
//go:build !gowaku_rln
// +build !gowaku_rln
package waku
import "github.com/status-im/go-waku/waku/v2/node"
func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
// Do nothing
}
func onStartRLN(wakuNode *node.WakuNode, options Options) {
// Do nothing
}

58
waku/node_rln.go Normal file
View File

@ -0,0 +1,58 @@
//go:build gowaku_rln
// +build gowaku_rln
package waku
import (
"crypto/ecdsa"
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/go-rln/rln"
"github.com/status-im/go-waku/waku/v2/node"
)
var loadedCredentialsFromFile bool = false
func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
if options.RLNRelay.Enable {
if !options.Relay.Enable {
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
}
if !options.RLNRelay.Dynamic {
*nodeOpts = append(*nodeOpts, node.WithStaticRLNRelay(options.RLNRelay.PubsubTopic, options.RLNRelay.ContentTopic, rln.MembershipIndex(options.RLNRelay.MembershipIndex), nil))
} else {
var ethPrivKey *ecdsa.PrivateKey
if options.RLNRelay.ETHPrivateKey != "" {
k, err := crypto.ToECDSA(common.FromHex(options.RLNRelay.ETHPrivateKey))
failOnErr(err, "Invalid private key")
ethPrivKey = k
}
loaded, idKey, idCommitment, membershipIndex, err := getMembershipCredentials(options)
failOnErr(err, "Invalid membership credentials")
loadedCredentialsFromFile = loaded
*nodeOpts = append(*nodeOpts, node.WithDynamicRLNRelay(
options.RLNRelay.PubsubTopic,
options.RLNRelay.ContentTopic,
membershipIndex,
idKey,
idCommitment,
nil,
options.RLNRelay.ETHClientAddress,
ethPrivKey,
common.HexToAddress(options.RLNRelay.MembershipContractAddress),
))
}
}
}
func onStartRLN(wakuNode *node.WakuNode, options Options) {
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile {
err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), options.RLNRelay.CredentialsFile, []byte(options.KeyPasswd), options.Overwrite)
failOnErr(err, "Could not write membership credentials file")
}
}

View File

@ -1,3 +1,6 @@
//go:build gowaku_rln
// +build gowaku_rln
package waku
import (

View File

@ -2,7 +2,6 @@ package node
import (
"context"
"encoding/hex"
"errors"
"fmt"
"net"
@ -24,7 +23,6 @@ import (
ma "github.com/multiformats/go-multiaddr"
"go.opencensus.io/stats"
r "github.com/status-im/go-rln/rln"
rendezvous "github.com/status-im/go-waku-rendezvous"
"github.com/status-im/go-waku/logging"
"github.com/status-im/go-waku/waku/try"
@ -35,7 +33,6 @@ import (
"github.com/status-im/go-waku/waku/v2/protocol/lightpush"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/relay"
"github.com/status-im/go-waku/waku/v2/protocol/rln"
"github.com/status-im/go-waku/waku/v2/protocol/store"
"github.com/status-im/go-waku/waku/v2/protocol/swap"
@ -51,6 +48,17 @@ type Peer struct {
type storeFactory func(w *WakuNode) store.Store
type MembershipKeyPair = struct {
IDKey [32]byte
IDCommitment [32]byte
}
type RLNRelay interface {
MembershipKeyPair() MembershipKeyPair
MembershipIndex() uint
AppendRLNProof(msg *pb.WakuMessage, senderEpochTime time.Time) error
}
type WakuNode struct {
host host.Host
opts *WakuNodeParameters
@ -62,7 +70,7 @@ type WakuNode struct {
rendezvous *rendezvous.RendezvousService
store store.Store
swap *swap.WakuSwap
rlnRelay *rln.WakuRLNRelay
rlnRelay RLNRelay
wakuFlag utils.WakuEnrBitfield
localNode *enode.LocalNode
@ -391,11 +399,6 @@ func (w *WakuNode) Relay() *relay.WakuRelay {
return w.relay
}
// RLNRelay is used to access any operation related to Waku RLN protocol
func (w *WakuNode) RLNRelay() *rln.WakuRLNRelay {
return w.rlnRelay
}
// Store is used to access any operation related to Waku Store protocol
func (w *WakuNode) Store() store.Store {
return w.store
@ -661,78 +664,3 @@ func (w *WakuNode) Peers() ([]*Peer, error) {
}
return peers, nil
}
func (w *WakuNode) mountRlnRelay() error {
// check whether inputs are provided
// relay protocol is the prerequisite of rln-relay
if w.Relay() == nil {
return errors.New("relay protocol is required")
}
// check whether the pubsub topic is supported at the relay level
topicFound := false
for _, t := range w.Relay().Topics() {
if t == w.opts.rlnRelayPubsubTopic {
topicFound = true
break
}
}
if !topicFound {
return errors.New("relay protocol does not support the configured pubsub topic")
}
if !w.opts.rlnRelayDynamic {
w.log.Info("setting up waku-rln-relay in off-chain mode")
// set up rln relay inputs
groupKeys, memKeyPair, memIndex, err := rln.StaticSetup(w.opts.rlnRelayMemIndex)
if err != nil {
return err
}
// mount rlnrelay in off-chain mode with a static group of users
w.rlnRelay, err = rln.RlnRelayStatic(w.ctx, w.relay, groupKeys, memKeyPair, memIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.log)
if err != nil {
return err
}
w.log.Info("membership id key", zap.String("IDKey", hex.EncodeToString(memKeyPair.IDKey[:])))
w.log.Info("membership id commitment key", zap.String("IDCommitment", hex.EncodeToString(memKeyPair.IDCommitment[:])))
// check the correct construction of the tree by comparing the calculated root against the expected root
// no error should happen as it is already captured in the unit tests
root, err := w.rlnRelay.RLN.GetMerkleRoot()
if err != nil {
return err
}
expectedRoot := r.STATIC_GROUP_MERKLE_ROOT
if hex.EncodeToString(root[:]) != expectedRoot {
return errors.New("root mismatch: something went wrong not in Merkle tree construction")
}
w.log.Info("the calculated root", zap.String("root", hex.EncodeToString(root[:])))
} else {
w.log.Info("setting up waku-rln-relay in on-chain mode")
// check if the peer has provided its rln credentials
var memKeyPair *r.MembershipKeyPair
if w.opts.rlnRelayIDCommitment != nil && w.opts.rlnRelayIDKey != nil {
memKeyPair = &r.MembershipKeyPair{
IDCommitment: *w.opts.rlnRelayIDCommitment,
IDKey: *w.opts.rlnRelayIDKey,
}
}
// mount the rln relay protocol in the on-chain/dynamic mode
var err error
w.rlnRelay, err = rln.RlnRelayDynamic(context.Background(), w.relay, w.opts.rlnETHClientAddress, w.opts.rlnETHPrivateKey, w.opts.rlnMembershipContractAddress, memKeyPair, w.opts.rlnRelayMemIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.log)
if err != nil {
return err
}
}
w.log.Info("mounted waku RLN relay", zap.String("pubsubTopic", w.opts.rlnRelayPubsubTopic), zap.String("contentTopic", w.opts.rlnRelayContentTopic))
return nil
}

View File

@ -0,0 +1,13 @@
//go:build !gowaku_rln
// +build !gowaku_rln
package node
// RLNRelay is used to access any operation related to Waku RLN protocol
func (w *WakuNode) RLNRelay() RLNRelay {
return nil
}
func (w *WakuNode) mountRlnRelay() error {
return nil
}

View File

@ -0,0 +1,96 @@
//go:build gowaku_rln
// +build gowaku_rln
package node
import (
"context"
"encoding/hex"
"errors"
r "github.com/status-im/go-rln/rln"
"github.com/status-im/go-waku/waku/v2/protocol/rln"
"go.uber.org/zap"
)
// RLNRelay is used to access any operation related to Waku RLN protocol
func (w *WakuNode) RLNRelay() RLNRelay {
return w.rlnRelay
}
func (w *WakuNode) mountRlnRelay() error {
// check whether inputs are provided
// relay protocol is the prerequisite of rln-relay
if w.Relay() == nil {
return errors.New("relay protocol is required")
}
// check whether the pubsub topic is supported at the relay level
topicFound := false
for _, t := range w.Relay().Topics() {
if t == w.opts.rlnRelayPubsubTopic {
topicFound = true
break
}
}
if !topicFound {
return errors.New("relay protocol does not support the configured pubsub topic")
}
if !w.opts.rlnRelayDynamic {
w.log.Info("setting up waku-rln-relay in off-chain mode")
// set up rln relay inputs
groupKeys, memKeyPair, memIndex, err := rln.StaticSetup(w.opts.rlnRelayMemIndex)
if err != nil {
return err
}
// mount rlnrelay in off-chain mode with a static group of users
rlnRelay, err := rln.RlnRelayStatic(w.ctx, w.relay, groupKeys, memKeyPair, memIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.log)
if err != nil {
return err
}
w.rlnRelay = rlnRelay
w.log.Info("membership id key", zap.String("IDKey", hex.EncodeToString(memKeyPair.IDKey[:])))
w.log.Info("membership id commitment key", zap.String("IDCommitment", hex.EncodeToString(memKeyPair.IDCommitment[:])))
// check the correct construction of the tree by comparing the calculated root against the expected root
// no error should happen as it is already captured in the unit tests
root, err := rlnRelay.RLN.GetMerkleRoot()
if err != nil {
return err
}
expectedRoot := r.STATIC_GROUP_MERKLE_ROOT
if hex.EncodeToString(root[:]) != expectedRoot {
return errors.New("root mismatch: something went wrong not in Merkle tree construction")
}
w.log.Info("the calculated root", zap.String("root", hex.EncodeToString(root[:])))
} else {
w.log.Info("setting up waku-rln-relay in on-chain mode")
// check if the peer has provided its rln credentials
var memKeyPair *r.MembershipKeyPair
if w.opts.rlnRelayIDCommitment != nil && w.opts.rlnRelayIDKey != nil {
memKeyPair = &r.MembershipKeyPair{
IDCommitment: *w.opts.rlnRelayIDCommitment,
IDKey: *w.opts.rlnRelayIDKey,
}
}
// mount the rln relay protocol in the on-chain/dynamic mode
var err error
w.rlnRelay, err = rln.RlnRelayDynamic(context.Background(), w.relay, w.opts.rlnETHClientAddress, w.opts.rlnETHPrivateKey, w.opts.rlnMembershipContractAddress, memKeyPair, w.opts.rlnRelayMemIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.log)
if err != nil {
return err
}
}
w.log.Info("mounted waku RLN relay", zap.String("pubsubTopic", w.opts.rlnRelayPubsubTopic), zap.String("contentTopic", w.opts.rlnRelayContentTopic))
return nil
}

View File

@ -22,10 +22,9 @@ import (
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
r "github.com/status-im/go-rln/rln"
rendezvous "github.com/status-im/go-waku-rendezvous"
"github.com/status-im/go-waku/waku/v2/protocol/filter"
"github.com/status-im/go-waku/waku/v2/protocol/rln"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/store"
"github.com/status-im/go-waku/waku/v2/utils"
"go.uber.org/zap"
@ -84,13 +83,13 @@ type WakuNodeParameters struct {
discV5autoUpdate bool
enableRLN bool
rlnRelayMemIndex r.MembershipIndex
rlnRelayMemIndex uint
rlnRelayPubsubTopic string
rlnRelayContentTopic string
rlnRelayDynamic bool
rlnSpamHandler rln.SpamHandler
rlnRelayIDKey *r.IDKey
rlnRelayIDCommitment *r.IDCommitment
rlnSpamHandler func(message *pb.WakuMessage) error
rlnRelayIDKey *[32]byte
rlnRelayIDCommitment *[32]byte
rlnETHPrivateKey *ecdsa.PrivateKey
rlnETHClientAddress string
rlnMembershipContractAddress common.Address
@ -420,35 +419,6 @@ func WithSecureWebsockets(address string, port int, certPath string, keyPath str
}
}
func WithStaticRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, spamHandler rln.SpamHandler) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
params.rlnRelayDynamic = false
params.rlnRelayMemIndex = memberIndex
params.rlnRelayPubsubTopic = pubsubTopic
params.rlnRelayContentTopic = contentTopic
params.rlnSpamHandler = spamHandler
return nil
}
}
func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, idKey *r.IDKey, idCommitment *r.IDCommitment, spamHandler rln.SpamHandler, ethClientAddress string, ethPrivateKey *ecdsa.PrivateKey, membershipContractAddress common.Address) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
params.rlnRelayDynamic = true
params.rlnRelayMemIndex = memberIndex
params.rlnRelayIDKey = idKey
params.rlnRelayIDCommitment = idCommitment
params.rlnRelayPubsubTopic = pubsubTopic
params.rlnRelayContentTopic = contentTopic
params.rlnSpamHandler = spamHandler
params.rlnETHClientAddress = ethClientAddress
params.rlnETHPrivateKey = ethPrivateKey
params.rlnMembershipContractAddress = membershipContractAddress
return nil
}
}
// Default options used in the libp2p node
var DefaultLibP2POptions = []libp2p.Option{
libp2p.ChainOptions(

View File

@ -0,0 +1,41 @@
//go:build gowaku_rln
// +build gowaku_rln
package node
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common"
r "github.com/status-im/go-rln/rln"
"github.com/status-im/go-waku/waku/v2/protocol/rln"
)
func WithStaticRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, spamHandler rln.SpamHandler) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
params.rlnRelayDynamic = false
params.rlnRelayMemIndex = memberIndex
params.rlnRelayPubsubTopic = pubsubTopic
params.rlnRelayContentTopic = contentTopic
params.rlnSpamHandler = spamHandler
return nil
}
}
func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, idKey *r.IDKey, idCommitment *r.IDCommitment, spamHandler rln.SpamHandler, ethClientAddress string, ethPrivateKey *ecdsa.PrivateKey, membershipContractAddress common.Address) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
params.rlnRelayDynamic = true
params.rlnRelayMemIndex = memberIndex
params.rlnRelayIDKey = idKey
params.rlnRelayIDCommitment = idCommitment
params.rlnRelayPubsubTopic = pubsubTopic
params.rlnRelayContentTopic = contentTopic
params.rlnSpamHandler = spamHandler
params.rlnETHClientAddress = ethClientAddress
params.rlnETHPrivateKey = ethPrivateKey
params.rlnMembershipContractAddress = membershipContractAddress
return nil
}
}

View File

@ -100,7 +100,7 @@ func (s *WakuRLNRelaySuite) TestUpdateLogAndHasDuplicate() {
s.Require().False(result1) // No duplicate is found
// Add it to the log
added, err := rlnRelay.UpdateLog(wm1)
added, err := rlnRelay.updateLog(wm1)
s.Require().NoError(err)
s.Require().True(added)
@ -110,7 +110,7 @@ func (s *WakuRLNRelaySuite) TestUpdateLogAndHasDuplicate() {
s.Require().False(result2) // No duplicate is found
// Add it to the log
added, err = rlnRelay.UpdateLog(wm2)
added, err = rlnRelay.updateLog(wm2)
s.Require().NoError(err)
s.Require().True(added)

View File

@ -125,7 +125,7 @@ func (rln *WakuRLNRelay) HasDuplicate(msg *pb.WakuMessage) (bool, error) {
return matched, nil
}
func (rln *WakuRLNRelay) UpdateLog(msg *pb.WakuMessage) (bool, error) {
func (rln *WakuRLNRelay) updateLog(msg *pb.WakuMessage) (bool, error) {
// extracts the `ProofMetadata` of the supplied messages `msg` and
// saves it in the `nullifierLog` of the `rlnPeer`
@ -225,7 +225,7 @@ func (rln *WakuRLNRelay) ValidateMessage(msg *pb.WakuMessage, optionalTime *time
// insert the message to the log
// the result of `updateLog` is discarded because message insertion is guaranteed by the implementation i.e.,
// it will never error out
_, err = rln.UpdateLog(msg)
_, err = rln.updateLog(msg)
if err != nil {
return MessageValidationResult_Unknown, err
}
@ -270,7 +270,7 @@ func (r *WakuRLNRelay) MembershipIndex() r.MembershipIndex {
return r.membershipIndex
}
type SpamHandler func(message *pb.WakuMessage) error
type SpamHandler = func(message *pb.WakuMessage) error
// this function sets a validator for the waku messages published on the supplied pubsubTopic and contentTopic
// if contentTopic is empty, then validation takes place for All the messages published on the given pubsubTopic

10
waku_no_rln.go Normal file
View File

@ -0,0 +1,10 @@
//go:build !gowaku_rln
// +build !gowaku_rln
package main
import "github.com/urfave/cli/v2"
func rlnFlags() []cli.Flag {
return nil
}

74
waku_rln.go Normal file
View File

@ -0,0 +1,74 @@
//go:build gowaku_rln
// +build gowaku_rln
package main
import "github.com/urfave/cli/v2"
func rlnFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "rln-relay",
Value: false,
Usage: "Enable spam protection through rln-relay",
Destination: &options.RLNRelay.Enable,
},
&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",
Usage: "Enable waku-rln-relay with on-chain dynamic group management",
Destination: &options.RLNRelay.Dynamic,
},
&cli.StringFlag{
Name: "rln-relay-id",
Usage: "Rln relay identity secret key as a Hex string",
Destination: &options.RLNRelay.IDKey,
},
&cli.StringFlag{
Name: "rln-relay-id-commitment",
Usage: "Rln relay identity commitment key as a Hex string",
Destination: &options.RLNRelay.IDCommitment,
},
&cli.StringFlag{
Name: "rln-relay-membership-credentials-file",
Usage: "RLN relay membership credentials file",
Value: "rlnCredentials.txt",
Destination: &options.RLNRelay.CredentialsFile,
},
// TODO: this is a good candidate option for subcommands
// TODO: consider accepting a private key file and passwd
&cli.StringFlag{
Name: "eth-private-key",
Usage: "Ethereum Goerli testnet account private key used for registering in member contract",
Destination: &options.RLNRelay.ETHPrivateKey,
},
&cli.StringFlag{
Name: "eth-client-address",
Usage: "Ethereum testnet client address",
Value: "ws://localhost:8545",
Destination: &options.RLNRelay.ETHClientAddress,
},
&cli.StringFlag{
Name: "eth-mem-contract-address",
Usage: "Address of membership contract on an Ethereum testnet",
Destination: &options.RLNRelay.MembershipContractAddress,
},
}
}