mirror of https://github.com/status-im/go-waku.git
fix: chat2 rln credentials
This commit is contained in:
parent
448781687e
commit
dc0968ca0a
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/status-im/go-waku/waku/v2/protocol/lightpush"
|
"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/pb"
|
||||||
"github.com/status-im/go-waku/waku/v2/protocol/store"
|
"github.com/status-im/go-waku/waku/v2/protocol/store"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func execute(options Options) {
|
func execute(options Options) {
|
||||||
|
@ -48,7 +49,13 @@ func execute(options Options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.RLNRelay.Dynamic {
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -114,7 +121,7 @@ func execute(options Options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.RLNRelay.Enable && options.RLNRelay.Dynamic {
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
return
|
return
|
||||||
|
|
|
@ -218,6 +218,12 @@ func getFlags() []cli.Flag {
|
||||||
Value: "",
|
Value: "",
|
||||||
Destination: &options.RLNRelay.CredentialsPath,
|
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: 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
|
||||||
&cli.GenericFlag{
|
&cli.GenericFlag{
|
||||||
|
|
|
@ -30,6 +30,7 @@ type RelayOptions struct {
|
||||||
type RLNRelayOptions struct {
|
type RLNRelayOptions struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
CredentialsPath string
|
CredentialsPath string
|
||||||
|
CredentialsPassword string
|
||||||
MembershipIndex int
|
MembershipIndex int
|
||||||
PubsubTopic string
|
PubsubTopic string
|
||||||
ContentTopic string
|
ContentTopic string
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -12,8 +12,6 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var loadedCredentialsFromFile bool = false
|
|
||||||
|
|
||||||
func checkForRLN(logger *zap.Logger, 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 {
|
||||||
|
@ -27,12 +25,15 @@ func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeO
|
||||||
if options.RLNRelay.ETHPrivateKey != nil {
|
if options.RLNRelay.ETHPrivateKey != nil {
|
||||||
ethPrivKey = options.RLNRelay.ETHPrivateKey
|
ethPrivKey = options.RLNRelay.ETHPrivateKey
|
||||||
}
|
}
|
||||||
|
membershipCredentials, err := node.GetMembershipCredentials(
|
||||||
loaded, membershipCredentials, err := getMembershipCredentials(logger, options)
|
logger,
|
||||||
|
options.RLNRelay.CredentialsPath,
|
||||||
|
options.RLNRelay.CredentialsPassword,
|
||||||
|
options.RLNRelay.MembershipContractAddress,
|
||||||
|
uint(options.RLNRelay.MembershipIndex),
|
||||||
|
)
|
||||||
failOnErr(err, "Invalid membership credentials")
|
failOnErr(err, "Invalid membership credentials")
|
||||||
|
|
||||||
loadedCredentialsFromFile = loaded
|
|
||||||
|
|
||||||
*nodeOpts = append(*nodeOpts, node.WithDynamicRLNRelay(
|
*nodeOpts = append(*nodeOpts, node.WithDynamicRLNRelay(
|
||||||
options.RLNRelay.PubsubTopic,
|
options.RLNRelay.PubsubTopic,
|
||||||
options.RLNRelay.ContentTopic,
|
options.RLNRelay.ContentTopic,
|
||||||
|
@ -47,8 +48,8 @@ func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeO
|
||||||
}
|
}
|
||||||
|
|
||||||
func onStartRLN(wakuNode *node.WakuNode, options Options) {
|
func onStartRLN(wakuNode *node.WakuNode, options Options) {
|
||||||
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && !loadedCredentialsFromFile && options.RLNRelay.CredentialsPath != "" {
|
if options.RLNRelay.Enable && options.RLNRelay.Dynamic && options.RLNRelay.CredentialsPath != "" {
|
||||||
err := writeRLNMembershipCredentialsToFile(wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress(), options.RLNRelay.CredentialsPath, []byte(options.KeyPasswd), options.Overwrite)
|
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")
|
failOnErr(err, "Could not write membership credentials file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ type RelayOptions struct {
|
||||||
type RLNRelayOptions struct {
|
type RLNRelayOptions struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
CredentialsPath string
|
CredentialsPath string
|
||||||
|
CredentialsPassword string
|
||||||
MembershipIndex int
|
MembershipIndex int
|
||||||
PubsubTopic string
|
PubsubTopic string
|
||||||
ContentTopic string
|
ContentTopic string
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//go:build gowaku_rln
|
//go:build gowaku_rln
|
||||||
// +build gowaku_rln
|
// +build gowaku_rln
|
||||||
|
|
||||||
package waku
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -13,14 +14,13 @@ import (
|
||||||
|
|
||||||
"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-waku/waku/v2/node"
|
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const RLN_CREDENTIALS_FILENAME = "rlnCredentials.txt"
|
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 == "" {
|
if path == "" {
|
||||||
return nil // we dont want to use a credentials file
|
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
|
return nil // no credentials to store
|
||||||
}
|
}
|
||||||
|
|
||||||
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
|
credentialsJSON, err := json.Marshal(MembershipCredentials{
|
||||||
|
|
||||||
if err := checkForFileExistence(path, overwrite); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
credentialsJSON, err := json.Marshal(node.MembershipCredentials{
|
|
||||||
Keypair: keyPair,
|
Keypair: keyPair,
|
||||||
Index: idx,
|
Index: idx,
|
||||||
Contract: contractAddress,
|
Contract: contractAddress,
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(string(credentialsJSON))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -56,60 +49,65 @@ func writeRLNMembershipCredentialsToFile(keyPair *rln.MembershipKeyPair, idx rln
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
|
||||||
|
|
||||||
return ioutil.WriteFile(path, output, 0600)
|
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)
|
src, err := ioutil.ReadFile(credentialsFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node.MembershipCredentials{}, err
|
return MembershipCredentials{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var encryptedK keystore.CryptoJSON
|
var encryptedK keystore.CryptoJSON
|
||||||
err = json.Unmarshal(src, &encryptedK)
|
err = json.Unmarshal(src, &encryptedK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node.MembershipCredentials{}, err
|
return MembershipCredentials{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
credentialsBytes, err := keystore.DecryptDataV3(encryptedK, passwd)
|
credentialsBytes, err := keystore.DecryptDataV3(encryptedK, passwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node.MembershipCredentials{}, err
|
return MembershipCredentials{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var credentials node.MembershipCredentials
|
var credentials MembershipCredentials
|
||||||
err = json.Unmarshal(credentialsBytes, &credentials)
|
err = json.Unmarshal(credentialsBytes, &credentials)
|
||||||
|
|
||||||
return credentials, err
|
return credentials, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMembershipCredentials(logger *zap.Logger, options Options) (fromFile bool, credentials node.MembershipCredentials, err error) {
|
func GetMembershipCredentials(logger *zap.Logger, credentialsPath string, password string, membershipContract common.Address, membershipIndex uint) (credentials MembershipCredentials, err error) {
|
||||||
if options.RLNRelay.CredentialsPath == "" { // Not using a file
|
if credentialsPath == "" { // Not using a file
|
||||||
return false, node.MembershipCredentials{
|
return MembershipCredentials{
|
||||||
Contract: options.RLNRelay.MembershipContractAddress,
|
Contract: membershipContract,
|
||||||
}, nil
|
}, 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 _, err = os.Stat(credentialsFilePath); err == nil {
|
||||||
if credentials, err := loadMembershipCredentialsFromFile(credentialsFilePath, options.KeyPasswd); err != nil {
|
if credentials, err := loadMembershipCredentialsFromFile(credentialsFilePath, password); err != 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)
|
||||||
} else {
|
} else {
|
||||||
logger.Info("loaded rln credentials", zap.String("filepath", credentialsFilePath))
|
logger.Info("loaded rln credentials", zap.String("filepath", credentialsFilePath))
|
||||||
if (bytes.Equal(credentials.Contract.Bytes(), common.Address{}.Bytes())) {
|
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) {
|
if os.IsNotExist(err) {
|
||||||
return false, node.MembershipCredentials{
|
return MembershipCredentials{
|
||||||
Keypair: nil,
|
Keypair: nil,
|
||||||
Index: uint(options.RLNRelay.MembershipIndex),
|
Index: membershipIndex,
|
||||||
Contract: options.RLNRelay.MembershipContractAddress,
|
Contract: membershipContract,
|
||||||
}, nil
|
}, 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)
|
||||||
}
|
}
|
|
@ -195,9 +195,8 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
|
||||||
}
|
}
|
||||||
errCh <- err
|
errCh <- err
|
||||||
subs.Unsubscribe()
|
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
|
return subs, err
|
||||||
})
|
})
|
||||||
|
|
|
@ -45,6 +45,12 @@ func rlnFlags() []cli.Flag {
|
||||||
Value: "",
|
Value: "",
|
||||||
Destination: &options.RLNRelay.CredentialsPath,
|
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: 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
|
||||||
&cli.GenericFlag{
|
&cli.GenericFlag{
|
||||||
|
|
Loading…
Reference in New Issue