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/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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -30,6 +30,7 @@ type RelayOptions struct {
|
|||
type RLNRelayOptions struct {
|
||||
Enable bool
|
||||
CredentialsPath string
|
||||
CredentialsPassword string
|
||||
MembershipIndex int
|
||||
PubsubTopic 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"
|
||||
)
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ type RelayOptions struct {
|
|||
type RLNRelayOptions struct {
|
||||
Enable bool
|
||||
CredentialsPath string
|
||||
CredentialsPassword string
|
||||
MembershipIndex int
|
||||
PubsubTopic string
|
||||
ContentTopic string
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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{
|
||||
|
|
Loading…
Reference in New Issue