From dc0968ca0a5d9faeb6d09add94b8156cd04ba061 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 8 Nov 2022 16:20:08 -0400 Subject: [PATCH] fix: chat2 rln credentials --- examples/chat2/exec.go | 11 ++- examples/chat2/flags.go | 6 ++ examples/chat2/options.go | 1 + examples/chat2/rln-credentials.go | 102 -------------------------- waku/node_rln.go | 17 +++-- waku/options.go | 1 + waku/{ => v2/node}/rln-credentials.go | 56 +++++++------- waku/v2/protocol/rln/web3.go | 3 +- waku_rln.go | 6 ++ 9 files changed, 60 insertions(+), 143 deletions(-) delete mode 100644 examples/chat2/rln-credentials.go rename waku/{ => v2/node}/rln-credentials.go (54%) diff --git a/examples/chat2/exec.go b/examples/chat2/exec.go index 54c32c02..f2026353 100644 --- a/examples/chat2/exec.go +++ b/examples/chat2/exec.go @@ -14,6 +14,7 @@ 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/store" + "github.com/status-im/go-waku/waku/v2/utils" ) func execute(options Options) { @@ -48,7 +49,13 @@ func execute(options Options) { } if options.RLNRelay.Dynamic { - membershipCredentials, err := getMembershipCredentials(options.RLNRelay) + membershipCredentials, err := node.GetMembershipCredentials( + utils.Logger(), + options.RLNRelay.CredentialsPath, + options.RLNRelay.CredentialsPassword, + options.RLNRelay.MembershipContractAddress, + uint(options.RLNRelay.MembershipIndex), + ) if err != nil { fmt.Println(err) return @@ -114,7 +121,7 @@ func execute(options Options) { } if options.RLNRelay.Enable && options.RLNRelay.Dynamic { - err := writeRLNMembershipCredentialsToFile(options.RLNRelay.CredentialsPath, wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress()) + err := node.WriteRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress(), options.RLNRelay.CredentialsPath, []byte(options.RLNRelay.CredentialsPassword)) if err != nil { fmt.Println(err.Error()) return diff --git a/examples/chat2/flags.go b/examples/chat2/flags.go index 2c93170a..a80bcf64 100644 --- a/examples/chat2/flags.go +++ b/examples/chat2/flags.go @@ -218,6 +218,12 @@ func getFlags() []cli.Flag { Value: "", Destination: &options.RLNRelay.CredentialsPath, }, + &cli.StringFlag{ + Name: "rln-relay-cred-password", + Value: "", + Usage: "Password for encrypting RLN credentials", + Destination: &options.RLNRelay.CredentialsPassword, + }, // TODO: this is a good candidate option for subcommands // TODO: consider accepting a private key file and passwd &cli.GenericFlag{ diff --git a/examples/chat2/options.go b/examples/chat2/options.go index fd557e2c..eeabbac7 100644 --- a/examples/chat2/options.go +++ b/examples/chat2/options.go @@ -30,6 +30,7 @@ type RelayOptions struct { type RLNRelayOptions struct { Enable bool CredentialsPath string + CredentialsPassword string MembershipIndex int PubsubTopic string ContentTopic string diff --git a/examples/chat2/rln-credentials.go b/examples/chat2/rln-credentials.go deleted file mode 100644 index 71bab0b9..00000000 --- a/examples/chat2/rln-credentials.go +++ /dev/null @@ -1,102 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "github.com/ethereum/go-ethereum/common" - "github.com/status-im/go-waku/waku/v2/node" - "github.com/waku-org/go-zerokit-rln/rln" -) - -const RLN_CREDENTIALS_FILENAME = "rlnCredentials.txt" - -func fileExists(path string) bool { - if _, err := os.Stat(path); err == nil { - return false - - } else if errors.Is(err, os.ErrNotExist) { - return false - - } else { - return false - } -} - -func writeRLNMembershipCredentialsToFile(path string, keyPair *rln.MembershipKeyPair, idx rln.MembershipIndex, contractAddress common.Address) error { - if path == "" { - return nil // No path to save file - } - - path = filepath.Join(path, RLN_CREDENTIALS_FILENAME) - if fileExists(path) { - return nil - } - - if keyPair == nil { - return nil // No credentials to write - } - - credentialsJSON, err := json.Marshal(node.MembershipCredentials{ - Keypair: &rln.MembershipKeyPair{ - IDKey: keyPair.IDKey, - IDCommitment: keyPair.IDCommitment, - }, - Index: idx, - Contract: contractAddress, - }) - if err != nil { - return err - } - - return ioutil.WriteFile(path, credentialsJSON, 0600) -} - -func loadMembershipCredentialsFromFile(rlnCredentialsPath string) (node.MembershipCredentials, error) { - src, err := ioutil.ReadFile(rlnCredentialsPath) - if err != nil { - return node.MembershipCredentials{}, err - } - - var credentials node.MembershipCredentials - err = json.Unmarshal(src, &credentials) - - return credentials, err -} - -func getMembershipCredentials(options RLNRelayOptions) (credentials node.MembershipCredentials, err error) { - path := options.CredentialsPath - - if path == "" { - return node.MembershipCredentials{ - Contract: options.MembershipContractAddress, - }, nil - } - - path = filepath.Join(path, RLN_CREDENTIALS_FILENAME) - _, osErr := os.Stat(path) - if osErr == nil { - if credentials, err := loadMembershipCredentialsFromFile(path); err != nil { - return node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) - } else { - if (bytes.Equal(credentials.Contract.Bytes(), common.Address{}.Bytes())) { - credentials.Contract = options.MembershipContractAddress - } - return credentials, nil - } - } - - if os.IsNotExist(osErr) { - return node.MembershipCredentials{ - Index: uint(options.MembershipIndex), - Contract: options.MembershipContractAddress, - }, nil - } - - return node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) -} diff --git a/waku/node_rln.go b/waku/node_rln.go index 2a8c8efc..7c2743ec 100644 --- a/waku/node_rln.go +++ b/waku/node_rln.go @@ -12,8 +12,6 @@ import ( "go.uber.org/zap" ) -var loadedCredentialsFromFile bool = false - func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeOption) { if options.RLNRelay.Enable { if !options.Relay.Enable { @@ -27,12 +25,15 @@ func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeO if options.RLNRelay.ETHPrivateKey != nil { ethPrivKey = options.RLNRelay.ETHPrivateKey } - - loaded, membershipCredentials, err := getMembershipCredentials(logger, options) + membershipCredentials, err := node.GetMembershipCredentials( + logger, + options.RLNRelay.CredentialsPath, + options.RLNRelay.CredentialsPassword, + options.RLNRelay.MembershipContractAddress, + uint(options.RLNRelay.MembershipIndex), + ) failOnErr(err, "Invalid membership credentials") - loadedCredentialsFromFile = loaded - *nodeOpts = append(*nodeOpts, node.WithDynamicRLNRelay( options.RLNRelay.PubsubTopic, options.RLNRelay.ContentTopic, @@ -47,8 +48,8 @@ func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeO } func onStartRLN(wakuNode *node.WakuNode, options Options) { - if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile && options.RLNRelay.CredentialsPath != "" { - err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress(), options.RLNRelay.CredentialsPath, []byte(options.KeyPasswd), options.Overwrite) + if options.RLNRelay.Enable && options.RLNRelay.Dynamic && options.RLNRelay.CredentialsPath != "" { + err := node.WriteRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress(), options.RLNRelay.CredentialsPath, []byte(options.RLNRelay.CredentialsPassword)) failOnErr(err, "Could not write membership credentials file") } } diff --git a/waku/options.go b/waku/options.go index c63b2d7f..c6d10e1a 100644 --- a/waku/options.go +++ b/waku/options.go @@ -31,6 +31,7 @@ type RelayOptions struct { type RLNRelayOptions struct { Enable bool CredentialsPath string + CredentialsPassword string MembershipIndex int PubsubTopic string ContentTopic string diff --git a/waku/rln-credentials.go b/waku/v2/node/rln-credentials.go similarity index 54% rename from waku/rln-credentials.go rename to waku/v2/node/rln-credentials.go index ae264492..29adf3da 100644 --- a/waku/rln-credentials.go +++ b/waku/v2/node/rln-credentials.go @@ -1,11 +1,12 @@ //go:build gowaku_rln // +build gowaku_rln -package waku +package node import ( "bytes" "encoding/json" + "errors" "fmt" "io/ioutil" "os" @@ -13,14 +14,13 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" - "github.com/status-im/go-waku/waku/v2/node" "github.com/waku-org/go-zerokit-rln/rln" "go.uber.org/zap" ) const RLN_CREDENTIALS_FILENAME = "rlnCredentials.txt" -func writeRLNMembershipCredentialsToFile(keyPair *rln.MembershipKeyPair, idx rln.MembershipIndex, contractAddress common.Address, path string, passwd []byte, overwrite bool) error { +func WriteRLNMembershipCredentialsToFile(keyPair *rln.MembershipKeyPair, idx rln.MembershipIndex, contractAddress common.Address, path string, passwd []byte) error { if path == "" { return nil // we dont want to use a credentials file } @@ -29,19 +29,12 @@ func writeRLNMembershipCredentialsToFile(keyPair *rln.MembershipKeyPair, idx rln return nil // no credentials to store } - path = filepath.Join(path, RLN_CREDENTIALS_FILENAME) - - if err := checkForFileExistence(path, overwrite); err != nil { - return err - } - - credentialsJSON, err := json.Marshal(node.MembershipCredentials{ + credentialsJSON, err := json.Marshal(MembershipCredentials{ Keypair: keyPair, Index: idx, Contract: contractAddress, }) - fmt.Println(string(credentialsJSON)) if err != nil { return err } @@ -56,60 +49,65 @@ func writeRLNMembershipCredentialsToFile(keyPair *rln.MembershipKeyPair, idx rln return err } + path = filepath.Join(path, RLN_CREDENTIALS_FILENAME) + return ioutil.WriteFile(path, output, 0600) } -func loadMembershipCredentialsFromFile(credentialsFilePath string, passwd string) (node.MembershipCredentials, error) { +func loadMembershipCredentialsFromFile(credentialsFilePath string, passwd string) (MembershipCredentials, error) { src, err := ioutil.ReadFile(credentialsFilePath) if err != nil { - return node.MembershipCredentials{}, err + return MembershipCredentials{}, err } var encryptedK keystore.CryptoJSON err = json.Unmarshal(src, &encryptedK) if err != nil { - return node.MembershipCredentials{}, err + return MembershipCredentials{}, err } credentialsBytes, err := keystore.DecryptDataV3(encryptedK, passwd) if err != nil { - return node.MembershipCredentials{}, err + return MembershipCredentials{}, err } - var credentials node.MembershipCredentials + var credentials MembershipCredentials err = json.Unmarshal(credentialsBytes, &credentials) return credentials, err } -func getMembershipCredentials(logger *zap.Logger, options Options) (fromFile bool, credentials node.MembershipCredentials, err error) { - if options.RLNRelay.CredentialsPath == "" { // Not using a file - return false, node.MembershipCredentials{ - Contract: options.RLNRelay.MembershipContractAddress, +func GetMembershipCredentials(logger *zap.Logger, credentialsPath string, password string, membershipContract common.Address, membershipIndex uint) (credentials MembershipCredentials, err error) { + if credentialsPath == "" { // Not using a file + return MembershipCredentials{ + Contract: membershipContract, }, nil } - credentialsFilePath := filepath.Join(options.RLNRelay.CredentialsPath, RLN_CREDENTIALS_FILENAME) + credentialsFilePath := filepath.Join(credentialsPath, RLN_CREDENTIALS_FILENAME) if _, err = os.Stat(credentialsFilePath); err == nil { - if credentials, err := loadMembershipCredentialsFromFile(credentialsFilePath, options.KeyPasswd); err != nil { - return false, node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) + if credentials, err := loadMembershipCredentialsFromFile(credentialsFilePath, password); err != nil { + return MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) } else { logger.Info("loaded rln credentials", zap.String("filepath", credentialsFilePath)) if (bytes.Equal(credentials.Contract.Bytes(), common.Address{}.Bytes())) { - credentials.Contract = options.RLNRelay.MembershipContractAddress + credentials.Contract = membershipContract } - return true, credentials, nil + if (bytes.Equal(membershipContract.Bytes(), common.Address{}.Bytes())) { + return MembershipCredentials{}, errors.New("no contract address specified") + } + return credentials, nil } } if os.IsNotExist(err) { - return false, node.MembershipCredentials{ + return MembershipCredentials{ Keypair: nil, - Index: uint(options.RLNRelay.MembershipIndex), - Contract: options.RLNRelay.MembershipContractAddress, + Index: membershipIndex, + Contract: membershipContract, }, nil } - return false, node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) + return MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) } diff --git a/waku/v2/protocol/rln/web3.go b/waku/v2/protocol/rln/web3.go index fa04bdc3..d39d8acf 100644 --- a/waku/v2/protocol/rln/web3.go +++ b/waku/v2/protocol/rln/web3.go @@ -195,10 +195,9 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi } errCh <- err subs.Unsubscribe() + rln.log.Error("subscribing to rln events", zap.Error(err)) } - rln.log.Error("subscribing to rln events", zap.Error(err)) - return subs, err }) defer subs.Unsubscribe() diff --git a/waku_rln.go b/waku_rln.go index d6539e19..66b38211 100644 --- a/waku_rln.go +++ b/waku_rln.go @@ -45,6 +45,12 @@ func rlnFlags() []cli.Flag { Value: "", Destination: &options.RLNRelay.CredentialsPath, }, + &cli.StringFlag{ + Name: "rln-relay-cred-password", + Value: "", + Usage: "Password for encrypting RLN credentials", + Destination: &options.RLNRelay.CredentialsPassword, + }, // TODO: this is a good candidate option for subcommands // TODO: consider accepting a private key file and passwd &cli.GenericFlag{