mirror of https://github.com/status-im/go-waku.git
fix: chat2 feedback
This commit is contained in:
parent
db85642862
commit
3716ebdf1d
|
@ -240,6 +240,9 @@ func (c *Chat) SendMessage(line string) {
|
||||||
|
|
||||||
err := c.publish(tCtx, line)
|
err := c.publish(tCtx, line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err.Error() == "validation failed" {
|
||||||
|
err = errors.New("message rate violation!")
|
||||||
|
}
|
||||||
c.ui.ErrorMessage(err)
|
c.ui.ErrorMessage(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
"github.com/status-im/go-waku/waku/v2/node"
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
@ -42,8 +43,12 @@ func execute(options Options) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registrationHandler := func(tx *types.Transaction) {
|
||||||
|
fmt.Println(fmt.Sprintf("You are registered to the rln membership contract, find details of your registration transaction in https://goerli.etherscan.io/tx/%s", tx.Hash()))
|
||||||
|
}
|
||||||
|
|
||||||
if options.RLNRelay.Dynamic {
|
if options.RLNRelay.Dynamic {
|
||||||
idKey, idCommitment, index, err := getMembershipCredentials(options.RLNRelay.CredentialsFile, options.RLNRelay.IDKey, options.RLNRelay.IDCommitment, options.RLNRelay.MembershipIndex)
|
idKey, idCommitment, index, err := getMembershipCredentials(options.RLNRelay.CredentialsPath, options.RLNRelay.IDKey, options.RLNRelay.IDCommitment, options.RLNRelay.MembershipIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -60,6 +65,7 @@ func execute(options Options) {
|
||||||
options.RLNRelay.ETHClientAddress,
|
options.RLNRelay.ETHClientAddress,
|
||||||
options.RLNRelay.ETHPrivateKey,
|
options.RLNRelay.ETHPrivateKey,
|
||||||
options.RLNRelay.MembershipContractAddress,
|
options.RLNRelay.MembershipContractAddress,
|
||||||
|
registrationHandler,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
opts = append(opts, node.WithStaticRLNRelay(
|
opts = append(opts, node.WithStaticRLNRelay(
|
||||||
|
@ -113,7 +119,7 @@ func execute(options Options) {
|
||||||
if options.RLNRelay.Enable && options.RLNRelay.Dynamic {
|
if options.RLNRelay.Enable && options.RLNRelay.Dynamic {
|
||||||
if options.RLNRelay.IDKey == "" && options.RLNRelay.IDCommitment == "" {
|
if options.RLNRelay.IDKey == "" && options.RLNRelay.IDCommitment == "" {
|
||||||
// Write membership credentials file only if the idkey and commitment are not specified
|
// Write membership credentials file only if the idkey and commitment are not specified
|
||||||
err := writeRLNMembershipCredentialsToFile(options.RLNRelay.CredentialsFile, wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex())
|
err := writeRLNMembershipCredentialsToFile(options.RLNRelay.CredentialsPath, wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
return
|
return
|
||||||
|
|
|
@ -214,10 +214,10 @@ func getFlags() []cli.Flag {
|
||||||
Destination: &options.RLNRelay.IDCommitment,
|
Destination: &options.RLNRelay.IDCommitment,
|
||||||
},
|
},
|
||||||
&cli.PathFlag{
|
&cli.PathFlag{
|
||||||
Name: "rln-relay-membership-credentials-file",
|
Name: "rln-relay-cred-path",
|
||||||
Usage: "RLN relay membership credentials file",
|
Usage: "The path for persisting rln-relay credential",
|
||||||
Value: "rlnCredentials.txt",
|
Value: "",
|
||||||
Destination: &options.RLNRelay.CredentialsFile,
|
Destination: &options.RLNRelay.CredentialsPath,
|
||||||
},
|
},
|
||||||
// TODO: this is a good candidate option for subcommands
|
// TODO: this is a good candidate option for subcommands
|
||||||
// TODO: consider accepting a private key file and passwd
|
// TODO: consider accepting a private key file and passwd
|
||||||
|
|
|
@ -29,7 +29,7 @@ type RelayOptions struct {
|
||||||
|
|
||||||
type RLNRelayOptions struct {
|
type RLNRelayOptions struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
CredentialsFile string
|
CredentialsPath string
|
||||||
MembershipIndex int
|
MembershipIndex int
|
||||||
PubsubTopic string
|
PubsubTopic string
|
||||||
ContentTopic string
|
ContentTopic string
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/status-im/go-rln/rln"
|
"github.com/status-im/go-rln/rln"
|
||||||
|
@ -21,6 +22,8 @@ type membershipCredentials struct {
|
||||||
Index rln.MembershipIndex `json:"rlnIndex"`
|
Index rln.MembershipIndex `json:"rlnIndex"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RLN_CREDENTIALS_FILENAME = "rlnCredentials.txt"
|
||||||
|
|
||||||
func fileExists(path string) bool {
|
func fileExists(path string) bool {
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -34,6 +37,8 @@ func fileExists(path string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRLNMembershipCredentialsToFile(path string, keyPair rln.MembershipKeyPair, idx rln.MembershipIndex) error {
|
func writeRLNMembershipCredentialsToFile(path string, keyPair rln.MembershipKeyPair, idx rln.MembershipIndex) error {
|
||||||
|
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
|
||||||
|
|
||||||
if fileExists(path) {
|
if fileExists(path) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -49,8 +54,8 @@ func writeRLNMembershipCredentialsToFile(path string, keyPair rln.MembershipKeyP
|
||||||
return ioutil.WriteFile(path, credentialsJSON, 0600)
|
return ioutil.WriteFile(path, credentialsJSON, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMembershipCredentialsFromFile(path string) (rln.MembershipKeyPair, rln.MembershipIndex, error) {
|
func loadMembershipCredentialsFromFile(rlnCredentialsPath string) (rln.MembershipKeyPair, rln.MembershipIndex, error) {
|
||||||
src, err := ioutil.ReadFile(path)
|
src, err := ioutil.ReadFile(rlnCredentialsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rln.MembershipKeyPair{}, rln.MembershipIndex(0), err
|
return rln.MembershipKeyPair{}, rln.MembershipIndex(0), err
|
||||||
}
|
}
|
||||||
|
@ -72,6 +77,7 @@ func getMembershipCredentials(path string, rlnIDKey string, rlnIDCommitment stri
|
||||||
|
|
||||||
var osErr error
|
var osErr error
|
||||||
if !valuesWereInput {
|
if !valuesWereInput {
|
||||||
|
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
|
||||||
if _, osErr = os.Stat(path); osErr == nil {
|
if _, osErr = os.Stat(path); osErr == nil {
|
||||||
if keyPair, index, err := loadMembershipCredentialsFromFile(path); err != nil {
|
if keyPair, index, err := loadMembershipCredentialsFromFile(path); err != nil {
|
||||||
return nil, nil, rln.MembershipIndex(0), fmt.Errorf("could not read membership credentials file: %w", err)
|
return nil, nil, rln.MembershipIndex(0), fmt.Errorf("could not read membership credentials file: %w", err)
|
||||||
|
|
|
@ -263,7 +263,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))))
|
nodeOpts = append(nodeOpts, node.WithDiscoveryV5(options.DiscV5.Port, bootnodes, options.DiscV5.AutoUpdate, pubsub.WithDiscoveryOpts(discovery.Limit(45), discovery.TTL(time.Duration(20)*time.Second))))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForRLN(options, &nodeOpts)
|
checkForRLN(logger, options, &nodeOpts)
|
||||||
|
|
||||||
wakuNode, err := node.New(ctx, nodeOpts...)
|
wakuNode, err := node.New(ctx, nodeOpts...)
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
|
|
||||||
package waku
|
package waku
|
||||||
|
|
||||||
import "github.com/status-im/go-waku/waku/v2/node"
|
import (
|
||||||
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
|
func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeOption) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,15 @@ package waku
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/status-im/go-rln/rln"
|
"github.com/status-im/go-rln/rln"
|
||||||
"github.com/status-im/go-waku/waku/v2/node"
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var loadedCredentialsFromFile bool = false
|
var loadedCredentialsFromFile bool = false
|
||||||
|
|
||||||
func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
|
func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeOption) {
|
||||||
if options.RLNRelay.Enable {
|
if options.RLNRelay.Enable {
|
||||||
if !options.Relay.Enable {
|
if !options.Relay.Enable {
|
||||||
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
|
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
|
||||||
|
@ -26,7 +28,7 @@ func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
|
||||||
ethPrivKey = options.RLNRelay.ETHPrivateKey
|
ethPrivKey = options.RLNRelay.ETHPrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded, idKey, idCommitment, membershipIndex, err := getMembershipCredentials(options)
|
loaded, idKey, idCommitment, membershipIndex, err := getMembershipCredentials(logger, options)
|
||||||
failOnErr(err, "Invalid membership credentials")
|
failOnErr(err, "Invalid membership credentials")
|
||||||
|
|
||||||
loadedCredentialsFromFile = loaded
|
loadedCredentialsFromFile = loaded
|
||||||
|
@ -41,14 +43,15 @@ func checkForRLN(options Options, nodeOpts *[]node.WakuNodeOption) {
|
||||||
options.RLNRelay.ETHClientAddress,
|
options.RLNRelay.ETHClientAddress,
|
||||||
ethPrivKey,
|
ethPrivKey,
|
||||||
options.RLNRelay.MembershipContractAddress,
|
options.RLNRelay.MembershipContractAddress,
|
||||||
|
nil,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onStartRLN(wakuNode *node.WakuNode, options Options) {
|
func onStartRLN(wakuNode *node.WakuNode, options Options) {
|
||||||
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile {
|
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile && options.RLNRelay.CredentialsPath != "" {
|
||||||
err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), options.RLNRelay.CredentialsFile, []byte(options.KeyPasswd), options.Overwrite)
|
err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), options.RLNRelay.CredentialsPath, []byte(options.KeyPasswd), options.Overwrite)
|
||||||
failOnErr(err, "Could not write membership credentials file")
|
failOnErr(err, "Could not write membership credentials file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ type RelayOptions struct {
|
||||||
|
|
||||||
type RLNRelayOptions struct {
|
type RLNRelayOptions struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
CredentialsFile string
|
CredentialsPath string
|
||||||
MembershipIndex int
|
MembershipIndex int
|
||||||
PubsubTopic string
|
PubsubTopic string
|
||||||
ContentTopic string
|
ContentTopic string
|
||||||
|
|
|
@ -8,10 +8,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/status-im/go-rln/rln"
|
"github.com/status-im/go-rln/rln"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type membershipCredentials struct {
|
type membershipCredentials struct {
|
||||||
|
@ -19,7 +21,11 @@ type membershipCredentials struct {
|
||||||
Index rln.MembershipIndex `json:"index"`
|
Index rln.MembershipIndex `json:"index"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RLN_CREDENTIALS_FILENAME = "rlnCredentials.txt"
|
||||||
|
|
||||||
func writeRLNMembershipCredentialsToFile(keyPair rln.MembershipKeyPair, idx rln.MembershipIndex, path string, passwd []byte, overwrite bool) error {
|
func writeRLNMembershipCredentialsToFile(keyPair rln.MembershipKeyPair, idx rln.MembershipIndex, path string, passwd []byte, overwrite bool) error {
|
||||||
|
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
|
||||||
|
|
||||||
if err := checkForFileExistence(path, overwrite); err != nil {
|
if err := checkForFileExistence(path, overwrite); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,8 +51,8 @@ func writeRLNMembershipCredentialsToFile(keyPair rln.MembershipKeyPair, idx rln.
|
||||||
return ioutil.WriteFile(path, output, 0600)
|
return ioutil.WriteFile(path, output, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMembershipCredentialsFromFile(path string, passwd string) (rln.MembershipKeyPair, rln.MembershipIndex, error) {
|
func loadMembershipCredentialsFromFile(credentialsFilePath string, passwd string) (rln.MembershipKeyPair, rln.MembershipIndex, error) {
|
||||||
src, err := ioutil.ReadFile(path)
|
src, err := ioutil.ReadFile(credentialsFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rln.MembershipKeyPair{}, rln.MembershipIndex(0), err
|
return rln.MembershipKeyPair{}, rln.MembershipIndex(0), err
|
||||||
}
|
}
|
||||||
|
@ -71,11 +77,13 @@ func loadMembershipCredentialsFromFile(path string, passwd string) (rln.Membersh
|
||||||
return credentials.Keypair, credentials.Index, err
|
return credentials.Keypair, credentials.Index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMembershipCredentials(options Options) (fromFile bool, idKey *rln.IDKey, idCommitment *rln.IDCommitment, index rln.MembershipIndex, err error) {
|
func getMembershipCredentials(logger *zap.Logger, options Options) (fromFile bool, idKey *rln.IDKey, idCommitment *rln.IDCommitment, index rln.MembershipIndex, err error) {
|
||||||
if _, err = os.Stat(options.RLNRelay.CredentialsFile); err == nil {
|
credentialsFilePath := filepath.Join(options.RLNRelay.CredentialsPath, RLN_CREDENTIALS_FILENAME)
|
||||||
if keyPair, index, err := loadMembershipCredentialsFromFile(options.RLNRelay.CredentialsFile, options.KeyPasswd); err != nil {
|
if _, err = os.Stat(credentialsFilePath); err == nil {
|
||||||
|
if keyPair, index, err := loadMembershipCredentialsFromFile(credentialsFilePath, options.KeyPasswd); err != nil {
|
||||||
return false, nil, nil, rln.MembershipIndex(0), fmt.Errorf("could not read membership credentials file: %w", err)
|
return false, nil, nil, rln.MembershipIndex(0), fmt.Errorf("could not read membership credentials file: %w", err)
|
||||||
} else {
|
} else {
|
||||||
|
logger.Info("loaded rln credentials", zap.String("filepath", credentialsFilePath))
|
||||||
return true, &keyPair.IDKey, &keyPair.IDCommitment, index, nil
|
return true, &keyPair.IDKey, &keyPair.IDCommitment, index, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,6 @@ func (w *WakuNode) mountRlnRelay() error {
|
||||||
|
|
||||||
w.rlnRelay = rlnRelay
|
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
|
// 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
|
// no error should happen as it is already captured in the unit tests
|
||||||
root, err := rlnRelay.RLN.GetMerkleRoot()
|
root, err := rlnRelay.RLN.GetMerkleRoot()
|
||||||
|
@ -84,7 +81,7 @@ func (w *WakuNode) mountRlnRelay() error {
|
||||||
|
|
||||||
// mount the rln relay protocol in the on-chain/dynamic mode
|
// mount the rln relay protocol in the on-chain/dynamic mode
|
||||||
var err error
|
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)
|
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.opts.rlnRegistrationHandler, w.log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/libp2p/go-libp2p"
|
"github.com/libp2p/go-libp2p"
|
||||||
"github.com/libp2p/go-libp2p-core/crypto"
|
"github.com/libp2p/go-libp2p-core/crypto"
|
||||||
|
@ -93,6 +94,7 @@ type WakuNodeParameters struct {
|
||||||
rlnETHPrivateKey *ecdsa.PrivateKey
|
rlnETHPrivateKey *ecdsa.PrivateKey
|
||||||
rlnETHClientAddress string
|
rlnETHClientAddress string
|
||||||
rlnMembershipContractAddress common.Address
|
rlnMembershipContractAddress common.Address
|
||||||
|
rlnRegistrationHandler func(tx *types.Transaction)
|
||||||
|
|
||||||
keepAliveInterval time.Duration
|
keepAliveInterval time.Duration
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ func WithStaticRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.M
|
||||||
|
|
||||||
// WithStaticRLNRelay enables the Waku V2 RLN protocol in onchain mode.
|
// WithStaticRLNRelay enables the Waku V2 RLN protocol in onchain mode.
|
||||||
// Requires the `gowaku_rln` build constrain (or the env variable RLN=true if building go-waku)
|
// Requires the `gowaku_rln` build constrain (or the env variable RLN=true if building go-waku)
|
||||||
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 {
|
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, registrationHandler rln.RegistrationHandler) WakuNodeOption {
|
||||||
return func(params *WakuNodeParameters) error {
|
return func(params *WakuNodeParameters) error {
|
||||||
params.enableRLN = true
|
params.enableRLN = true
|
||||||
params.rlnRelayDynamic = true
|
params.rlnRelayDynamic = true
|
||||||
|
@ -40,6 +40,7 @@ func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.
|
||||||
params.rlnETHClientAddress = ethClientAddress
|
params.rlnETHClientAddress = ethClientAddress
|
||||||
params.rlnETHPrivateKey = ethPrivateKey
|
params.rlnETHPrivateKey = ethPrivateKey
|
||||||
params.rlnMembershipContractAddress = membershipContractAddress
|
params.rlnMembershipContractAddress = membershipContractAddress
|
||||||
|
params.rlnRegistrationHandler = registrationHandler
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ func RlnRelayDynamic(
|
||||||
pubsubTopic string,
|
pubsubTopic string,
|
||||||
contentTopic string,
|
contentTopic string,
|
||||||
spamHandler SpamHandler,
|
spamHandler SpamHandler,
|
||||||
|
registrationHandler RegistrationHandler,
|
||||||
log *zap.Logger,
|
log *zap.Logger,
|
||||||
) (*WakuRLNRelay, error) {
|
) (*WakuRLNRelay, error) {
|
||||||
log = log.Named("rln-dynamic")
|
log = log.Named("rln-dynamic")
|
||||||
|
@ -114,6 +115,7 @@ func RlnRelayDynamic(
|
||||||
contentTopic: contentTopic,
|
contentTopic: contentTopic,
|
||||||
log: log,
|
log: log,
|
||||||
nullifierLog: make(map[r.Epoch][]r.ProofMetadata),
|
nullifierLog: make(map[r.Epoch][]r.ProofMetadata),
|
||||||
|
registrationHandler: registrationHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare rln membership key pair
|
// prepare rln membership key pair
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
proto "github.com/golang/protobuf/proto"
|
proto "github.com/golang/protobuf/proto"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
@ -26,6 +27,8 @@ const MAX_CLOCK_GAP_SECONDS = 20
|
||||||
// maximum allowed gap between the epochs of messages' RateLimitProofs
|
// maximum allowed gap between the epochs of messages' RateLimitProofs
|
||||||
const MAX_EPOCH_GAP = int64(MAX_CLOCK_GAP_SECONDS / r.EPOCH_UNIT_SECONDS)
|
const MAX_EPOCH_GAP = int64(MAX_CLOCK_GAP_SECONDS / r.EPOCH_UNIT_SECONDS)
|
||||||
|
|
||||||
|
type RegistrationHandler = func(tx *types.Transaction)
|
||||||
|
|
||||||
type WakuRLNRelay struct {
|
type WakuRLNRelay struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
|
@ -50,7 +53,8 @@ type WakuRLNRelay struct {
|
||||||
// the log of nullifiers and Shamir shares of the past messages grouped per epoch
|
// the log of nullifiers and Shamir shares of the past messages grouped per epoch
|
||||||
nullifierLog map[r.Epoch][]r.ProofMetadata
|
nullifierLog map[r.Epoch][]r.ProofMetadata
|
||||||
|
|
||||||
log *zap.Logger
|
registrationHandler RegistrationHandler
|
||||||
|
log *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rln *WakuRLNRelay) Stop() {
|
func (rln *WakuRLNRelay) Stop() {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
r "github.com/status-im/go-rln/rln"
|
r "github.com/status-im/go-rln/rln"
|
||||||
"github.com/status-im/go-waku/waku/v2/protocol/rln/contracts"
|
"github.com/status-im/go-waku/waku/v2/protocol/rln/contracts"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -23,7 +24,7 @@ func toBigInt(i []byte) *big.Int {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *ecdsa.PrivateKey, ethClientAddress string, membershipContractAddress common.Address, log *zap.Logger) (*r.MembershipIndex, error) {
|
func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *ecdsa.PrivateKey, ethClientAddress string, membershipContractAddress common.Address, registrationHandler RegistrationHandler, log *zap.Logger) (*r.MembershipIndex, error) {
|
||||||
backend, err := ethclient.Dial(ethClientAddress)
|
backend, err := ethclient.Dial(ethClientAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -57,6 +58,10 @@ func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *
|
||||||
|
|
||||||
log.Info("transaction broadcasted", zap.String("transactionHash", tx.Hash().Hex()))
|
log.Info("transaction broadcasted", zap.String("transactionHash", tx.Hash().Hex()))
|
||||||
|
|
||||||
|
if registrationHandler != nil {
|
||||||
|
registrationHandler(tx)
|
||||||
|
}
|
||||||
|
|
||||||
txReceipt, err := bind.WaitMined(ctx, backend, tx)
|
txReceipt, err := bind.WaitMined(ctx, backend, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,7 +100,7 @@ func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *
|
||||||
// into the membership contract whose address is in rlnPeer.membershipContractAddress
|
// into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||||
func (rln *WakuRLNRelay) Register(ctx context.Context) (*r.MembershipIndex, error) {
|
func (rln *WakuRLNRelay) Register(ctx context.Context) (*r.MembershipIndex, error) {
|
||||||
pk := rln.membershipKeyPair.IDCommitment
|
pk := rln.membershipKeyPair.IDCommitment
|
||||||
return register(ctx, pk, rln.ethAccountPrivateKey, rln.ethClientAddress, rln.membershipContractAddress, rln.log)
|
return register(ctx, pk, rln.ethAccountPrivateKey, rln.ethClientAddress, rln.membershipContractAddress, rln.registrationHandler, rln.log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// the types of inputs to this handler matches the MemberRegistered event/proc defined in the MembershipContract interface
|
// the types of inputs to this handler matches the MemberRegistered event/proc defined in the MembershipContract interface
|
||||||
|
@ -146,7 +151,7 @@ func (rln *WakuRLNRelay) HandleGroupUpdates(handler RegistrationEventHandler, er
|
||||||
select {
|
select {
|
||||||
case <-doneCh:
|
case <-doneCh:
|
||||||
return
|
return
|
||||||
case <-errCh:
|
case err := <-errCh:
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -179,7 +184,11 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
|
||||||
logSink := make(chan *contracts.RLNMemberRegistered)
|
logSink := make(chan *contracts.RLNMemberRegistered)
|
||||||
subs, err := rlnContract.WatchMemberRegistered(&bind.WatchOpts{Context: rln.ctx, Start: nil}, logSink)
|
subs, err := rlnContract.WatchMemberRegistered(&bind.WatchOpts{Context: rln.ctx, Start: nil}, logSink)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == rpc.ErrNotificationsUnsupported {
|
||||||
|
err = errors.New("notifications not supported. The node must support websockets")
|
||||||
|
}
|
||||||
errCh <- err
|
errCh <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer subs.Unsubscribe()
|
defer subs.Unsubscribe()
|
||||||
|
|
||||||
|
@ -197,10 +206,11 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
|
||||||
close(logSink)
|
close(logSink)
|
||||||
return
|
return
|
||||||
case err := <-subs.Err():
|
case err := <-subs.Err():
|
||||||
|
close(logSink)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rln.log.Error("watching new events", zap.Error(err))
|
rln.log.Error("watching new events", zap.Error(err))
|
||||||
|
errCh <- err
|
||||||
}
|
}
|
||||||
close(logSink)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ components:
|
||||||
properties:
|
properties:
|
||||||
payload:
|
payload:
|
||||||
type: string
|
type: string
|
||||||
|
format: byte
|
||||||
contentTopic:
|
contentTopic:
|
||||||
$ref: '#/components/schemas/ContentTopic'
|
$ref: '#/components/schemas/ContentTopic'
|
||||||
version:
|
version:
|
||||||
|
|
|
@ -53,7 +53,7 @@ func rlnFlags() []cli.Flag {
|
||||||
Name: "rln-relay-membership-credentials-file",
|
Name: "rln-relay-membership-credentials-file",
|
||||||
Usage: "RLN relay membership credentials file",
|
Usage: "RLN relay membership credentials file",
|
||||||
Value: "rlnCredentials.txt",
|
Value: "rlnCredentials.txt",
|
||||||
Destination: &options.RLNRelay.CredentialsFile,
|
Destination: &options.RLNRelay.CredentialsPath,
|
||||||
},
|
},
|
||||||
// TODO: this is a good candidate option for subcommands
|
// TODO: this is a good candidate option for subcommands
|
||||||
// TODO: consider accepting a private key file and passwd
|
// TODO: consider accepting a private key file and passwd
|
||||||
|
|
Loading…
Reference in New Issue