go-waku/waku/v2/node/rln-credentials.go

114 lines
3.1 KiB
Go

//go:build gowaku_rln
// +build gowaku_rln
package node
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"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) error {
if path == "" {
return nil // we dont want to use a credentials file
}
if keyPair == nil {
return nil // no credentials to store
}
credentialsJSON, err := json.Marshal(MembershipCredentials{
Keypair: keyPair,
Index: idx,
Contract: contractAddress,
})
if err != nil {
return err
}
encryptedCredentials, err := keystore.EncryptDataV3(credentialsJSON, passwd, keystore.StandardScryptN, keystore.StandardScryptP)
if err != nil {
return err
}
output, err := json.Marshal(encryptedCredentials)
if err != nil {
return err
}
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
return ioutil.WriteFile(path, output, 0600)
}
func loadMembershipCredentialsFromFile(credentialsFilePath string, passwd string) (MembershipCredentials, error) {
src, err := ioutil.ReadFile(credentialsFilePath)
if err != nil {
return MembershipCredentials{}, err
}
var encryptedK keystore.CryptoJSON
err = json.Unmarshal(src, &encryptedK)
if err != nil {
return MembershipCredentials{}, err
}
credentialsBytes, err := keystore.DecryptDataV3(encryptedK, passwd)
if err != nil {
return MembershipCredentials{}, err
}
var credentials MembershipCredentials
err = json.Unmarshal(credentialsBytes, &credentials)
return credentials, err
}
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(credentialsPath, RLN_CREDENTIALS_FILENAME)
if _, err = os.Stat(credentialsFilePath); err == nil {
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 = membershipContract
}
if (bytes.Equal(membershipContract.Bytes(), common.Address{}.Bytes())) {
return MembershipCredentials{}, errors.New("no contract address specified")
}
return credentials, nil
}
}
if os.IsNotExist(err) {
return MembershipCredentials{
Keypair: nil,
Index: membershipIndex,
Contract: membershipContract,
}, nil
}
return MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err)
}