chore(rln-relay): use the only key from keystore if only 1 exists

This commit is contained in:
Richard Ramos 2023-09-04 17:44:41 -04:00 committed by richΛrd
parent 08cabab41f
commit 8783cd2f45
14 changed files with 107 additions and 48 deletions

View File

@ -1,12 +1,12 @@
plugins: plugins:
golint: # golint:
enabled: true # enabled: true
gofmt: gofmt:
enabled: true enabled: true
govet: govet:
enabled: true enabled: true
# golangci-lint: # golangci-lint:
#enabled: true # enabled: true
exclude_patterns: exclude_patterns:
- "." - "."
- "**/*.pb.go" - "**/*.pb.go"

View File

@ -17,11 +17,12 @@ func rlnFlags() []cli.Flag {
Usage: "Enable spam protection through rln-relay", Usage: "Enable spam protection through rln-relay",
Destination: &options.RLNRelay.Enable, Destination: &options.RLNRelay.Enable,
}, },
&cli.UintFlag{ &cli.GenericFlag{
Name: "rln-relay-membership-index", Name: "rln-relay-cred-index",
Value: 0, Usage: "the index of the onchain commitment to use",
Usage: "the index of credentials to use", Value: &wcli.OptionalUint{
Destination: &options.RLNRelay.MembershipIndex, Value: &options.RLNRelay.MembershipIndex,
},
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "rln-relay-dynamic", Name: "rln-relay-dynamic",

View File

@ -17,7 +17,7 @@ func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuN
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay") failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
} }
if !options.RLNRelay.Dynamic { if !options.RLNRelay.Dynamic {
*nodeOpts = append(*nodeOpts, node.WithStaticRLNRelay(rln.MembershipIndex(options.RLNRelay.MembershipIndex), nil)) *nodeOpts = append(*nodeOpts, node.WithStaticRLNRelay((*rln.MembershipIndex)(options.RLNRelay.MembershipIndex), nil))
} else { } else {
// TODO: too many parameters in this function // TODO: too many parameters in this function
// consider passing a config struct instead // consider passing a config struct instead
@ -26,7 +26,7 @@ func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuN
options.RLNRelay.CredentialsPassword, options.RLNRelay.CredentialsPassword,
options.RLNRelay.TreePath, options.RLNRelay.TreePath,
options.RLNRelay.MembershipContractAddress, options.RLNRelay.MembershipContractAddress,
rln.MembershipIndex(options.RLNRelay.MembershipIndex), options.RLNRelay.MembershipIndex,
nil, nil,
options.RLNRelay.ETHClientAddress, options.RLNRelay.ETHClientAddress,
)) ))

View File

@ -40,7 +40,7 @@ type RLNRelayOptions struct {
CredentialsPath string CredentialsPath string
CredentialsPassword string CredentialsPassword string
TreePath string TreePath string
MembershipIndex uint MembershipIndex *uint
Dynamic bool Dynamic bool
ETHClientAddress string ETHClientAddress string
MembershipContractAddress common.Address MembershipContractAddress common.Address

View File

@ -54,13 +54,13 @@ func execute(options Options) {
options.RLNRelay.CredentialsPassword, options.RLNRelay.CredentialsPassword,
"", // Will use default tree path "", // Will use default tree path
options.RLNRelay.MembershipContractAddress, options.RLNRelay.MembershipContractAddress,
uint(options.RLNRelay.MembershipIndex), options.RLNRelay.MembershipIndex,
spamHandler, spamHandler,
options.RLNRelay.ETHClientAddress, options.RLNRelay.ETHClientAddress,
)) ))
} else { } else {
opts = append(opts, node.WithStaticRLNRelay( opts = append(opts, node.WithStaticRLNRelay(
uint(options.RLNRelay.MembershipIndex), options.RLNRelay.MembershipIndex,
spamHandler)) spamHandler))
} }
} }

View File

@ -36,8 +36,7 @@ func getFlags() []cli.Flag {
testCT, err := protocol.NewContentTopic("toy-chat", 3, "mingde", "proto") testCT, err := protocol.NewContentTopic("toy-chat", 3, "mingde", "proto")
if err != nil { if err != nil {
fmt.Println("Invalid contentTopic") panic("invalid contentTopic")
return nil
} }
testnetContentTopic := testCT.String() testnetContentTopic := testCT.String()
@ -190,11 +189,12 @@ func getFlags() []cli.Flag {
Usage: "Enable spam protection through rln-relay", Usage: "Enable spam protection through rln-relay",
Destination: &options.RLNRelay.Enable, Destination: &options.RLNRelay.Enable,
}, },
&cli.UintFlag{ &cli.GenericFlag{
Name: "rln-relay-membership-index", Name: "rln-relay-cred-index",
Value: 0, Usage: "the index of the onchain commitment to use",
Usage: "the index of credentials to use", Value: &wcli.OptionalUint{
Destination: &options.RLNRelay.MembershipIndex, Value: &options.RLNRelay.MembershipIndex,
},
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "rln-relay-dynamic", Name: "rln-relay-dynamic",

View File

@ -31,7 +31,7 @@ type RLNRelayOptions struct {
Enable bool Enable bool
CredentialsPath string CredentialsPath string
CredentialsPassword string CredentialsPassword string
MembershipIndex uint MembershipIndex *uint
Dynamic bool Dynamic bool
ETHClientAddress string ETHClientAddress string
MembershipContractAddress common.Address MembershipContractAddress common.Address

View File

@ -4,6 +4,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
"strconv"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -73,3 +74,33 @@ func (v *ChoiceValue) String() string {
} }
return *v.Value return *v.Value
} }
// OptionalUint represents a urfave/cli flag to store uint values that can be
// optionally set and not have any default value assigned to it
type OptionalUint struct {
Value **uint
}
// Set assigns a value to the flag only if it represents a valid uint value
func (v *OptionalUint) Set(value string) error {
if value != "" {
uintVal, err := strconv.ParseUint(value, 10, 0)
if err != nil {
return err
}
uVal := uint(uintVal)
*v.Value = &uVal
} else {
v.Value = nil
}
return nil
}
// String returns the string representation of the OptionalUint flag, if set
func (v *OptionalUint) String() string {
if v.Value == nil {
return ""
}
return fmt.Sprintf("%d", *v.Value)
}

View File

@ -38,14 +38,18 @@ func (w *WakuNode) setupRLNRelay() error {
if !w.opts.rlnRelayDynamic { if !w.opts.rlnRelayDynamic {
w.log.Info("setting up waku-rln-relay in off-chain mode") w.log.Info("setting up waku-rln-relay in off-chain mode")
index := uint(0)
if w.opts.rlnRelayMemIndex != nil {
index = *w.opts.rlnRelayMemIndex
}
// set up rln relay inputs // set up rln relay inputs
groupKeys, idCredential, err := static.Setup(w.opts.rlnRelayMemIndex) groupKeys, idCredential, err := static.Setup(index)
if err != nil { if err != nil {
return err return err
} }
groupManager, err = static.NewStaticGroupManager(groupKeys, idCredential, w.opts.rlnRelayMemIndex, rlnInstance, groupManager, err = static.NewStaticGroupManager(groupKeys, idCredential, index, rlnInstance, rootTracker, w.log)
rootTracker, w.log)
if err != nil { if err != nil {
return err return err
} }

View File

@ -94,7 +94,7 @@ type WakuNodeParameters struct {
enablePeerExchange bool enablePeerExchange bool
enableRLN bool enableRLN bool
rlnRelayMemIndex uint rlnRelayMemIndex *uint
rlnRelayDynamic bool rlnRelayDynamic bool
rlnSpamHandler func(message *pb.WakuMessage) error rlnSpamHandler func(message *pb.WakuMessage) error
rlnETHClientAddress string rlnETHClientAddress string

View File

@ -11,7 +11,7 @@ import (
// WithStaticRLNRelay enables the Waku V2 RLN protocol in offchain mode // WithStaticRLNRelay enables the Waku V2 RLN protocol in offchain 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 WithStaticRLNRelay(memberIndex r.MembershipIndex, spamHandler rln.SpamHandler) WakuNodeOption { func WithStaticRLNRelay(memberIndex *r.MembershipIndex, spamHandler rln.SpamHandler) WakuNodeOption {
return func(params *WakuNodeParameters) error { return func(params *WakuNodeParameters) error {
params.enableRLN = true params.enableRLN = true
params.rlnRelayDynamic = false params.rlnRelayDynamic = false
@ -23,7 +23,7 @@ func WithStaticRLNRelay(memberIndex r.MembershipIndex, spamHandler rln.SpamHandl
// WithDynamicRLNRelay enables the Waku V2 RLN protocol in onchain mode. // WithDynamicRLNRelay 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(keystorePath string, keystorePassword string, treePath string, membershipContract common.Address, membershipIndex uint, spamHandler rln.SpamHandler, ethClientAddress string) WakuNodeOption { func WithDynamicRLNRelay(keystorePath string, keystorePassword string, treePath string, membershipContract common.Address, membershipIndex *uint, spamHandler rln.SpamHandler, ethClientAddress string) WakuNodeOption {
return func(params *WakuNodeParameters) error { return func(params *WakuNodeParameters) error {
params.enableRLN = true params.enableRLN = true
params.rlnRelayDynamic = true params.rlnRelayDynamic = true

View File

@ -37,8 +37,9 @@ type DynamicGroupManager struct {
lastBlockProcessed uint64 lastBlockProcessed uint64
appKeystore *keystore.AppKeystore appKeystore *keystore.AppKeystore
keystorePassword string keystorePassword string
membershipIndexToLoad *uint
} }
func (gm *DynamicGroupManager) handler(events []*contracts.RLNMemberRegistered) error { func (gm *DynamicGroupManager) handler(events []*contracts.RLNMemberRegistered) error {
@ -104,7 +105,7 @@ type RegistrationHandler = func(tx *types.Transaction)
func NewDynamicGroupManager( func NewDynamicGroupManager(
ethClientAddr string, ethClientAddr string,
memContractAddr common.Address, memContractAddr common.Address,
membershipIndex uint, membershipIndexToLoad *uint,
appKeystore *keystore.AppKeystore, appKeystore *keystore.AppKeystore,
keystorePassword string, keystorePassword string,
reg prometheus.Registerer, reg prometheus.Registerer,
@ -116,11 +117,11 @@ func NewDynamicGroupManager(
web3Config := web3.NewConfig(ethClientAddr, memContractAddr) web3Config := web3.NewConfig(ethClientAddr, memContractAddr)
return &DynamicGroupManager{ return &DynamicGroupManager{
membershipIndex: membershipIndex, membershipIndexToLoad: membershipIndexToLoad,
appKeystore: appKeystore, appKeystore: appKeystore,
keystorePassword: keystorePassword, keystorePassword: keystorePassword,
MembershipFetcher: NewMembershipFetcher(web3Config, rlnInstance, rootTracker, log), MembershipFetcher: NewMembershipFetcher(web3Config, rlnInstance, rootTracker, log),
metrics: newMetrics(reg), metrics: newMetrics(reg),
}, nil }, nil
} }
@ -170,7 +171,7 @@ func (gm *DynamicGroupManager) loadCredential(ctx context.Context) error {
credentials, err := gm.appKeystore.GetMembershipCredentials( credentials, err := gm.appKeystore.GetMembershipCredentials(
gm.keystorePassword, gm.keystorePassword,
gm.membershipIndex, gm.membershipIndexToLoad,
keystore.NewMembershipContractInfo(gm.web3Config.ChainID, gm.web3Config.RegistryContract.Address)) keystore.NewMembershipContractInfo(gm.web3Config.ChainID, gm.web3Config.RegistryContract.Address))
if err != nil { if err != nil {
return err return err
@ -191,6 +192,7 @@ func (gm *DynamicGroupManager) loadCredential(ctx context.Context) error {
} }
gm.identityCredential = credentials.IdentityCredential gm.identityCredential = credentials.IdentityCredential
gm.membershipIndex = credentials.TreeIndex
return nil return nil
} }

View File

@ -81,10 +81,31 @@ func getKey(treeIndex rln.MembershipIndex, filterMembershipContract MembershipCo
} }
// GetMembershipCredentials decrypts and retrieves membership credentials from the keystore applying filters // GetMembershipCredentials decrypts and retrieves membership credentials from the keystore applying filters
func (k *AppKeystore) GetMembershipCredentials(keystorePassword string, treeIndex rln.MembershipIndex, filterMembershipContract MembershipContractInfo) (*MembershipCredentials, error) { func (k *AppKeystore) GetMembershipCredentials(keystorePassword string, index *rln.MembershipIndex, filterMembershipContract MembershipContractInfo) (*MembershipCredentials, error) {
key, err := getKey(treeIndex, filterMembershipContract) // If there is only one, and index to laod nil, assume 0,
if err != nil { // if there is more than one, complain if the index to load is nil
return nil, err
var key Key
var err error
if len(k.Credentials) == 1 {
// Only one credential, the tree index does not matter.
k.logger.Warn("automatically loading the only credential found on the keystore")
for k := range k.Credentials {
key = k // Obtain the first c
break
}
} else {
treeIndex := uint(0)
if index != nil {
treeIndex = *index
} else {
return nil, errors.New("the index of the onchain commitment to use was not specified")
}
key, err = getKey(treeIndex, filterMembershipContract)
if err != nil {
return nil, err
}
} }
credential, ok := k.Credentials[key] credential, ok := k.Credentials[key]
@ -108,7 +129,7 @@ func (k *AppKeystore) GetMembershipCredentials(keystorePassword string, treeInde
// AddMembershipCredentials inserts a membership credential to the keystore matching the application, appIdentifier and version filters. // AddMembershipCredentials inserts a membership credential to the keystore matching the application, appIdentifier and version filters.
func (k *AppKeystore) AddMembershipCredentials(newCredential MembershipCredentials, password string) error { func (k *AppKeystore) AddMembershipCredentials(newCredential MembershipCredentials, password string) error {
credentials, err := k.GetMembershipCredentials(password, newCredential.TreeIndex, newCredential.MembershipContractInfo) credentials, err := k.GetMembershipCredentials(password, &newCredential.TreeIndex, newCredential.MembershipContractInfo)
if err != nil { if err != nil {
return err return err
} }
@ -118,7 +139,7 @@ func (k *AppKeystore) AddMembershipCredentials(newCredential MembershipCredentia
return err return err
} }
if credentials != nil { if credentials != nil && credentials.TreeIndex == newCredential.TreeIndex && credentials.MembershipContractInfo.Equals(newCredential.MembershipContractInfo) {
return errors.New("credential already present") return errors.New("credential already present")
} }

View File

@ -149,7 +149,7 @@ func (s *WakuRLNRelayDynamicSuite) TestDynamicGroupManagement() {
membershipIndex := s.register(appKeystore, u1Credentials, s.u1PrivKey) membershipIndex := s.register(appKeystore, u1Credentials, s.u1PrivKey)
gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rlnInstance, rt, utils.Logger()) gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, &membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rlnInstance, rt, utils.Logger())
s.Require().NoError(err) s.Require().NoError(err)
// initialize the WakuRLNRelay // initialize the WakuRLNRelay
@ -236,7 +236,7 @@ func (s *WakuRLNRelayDynamicSuite) TestMerkleTreeConstruction() {
rlnInstance, rootTracker, err := GetRLNInstanceAndRootTracker(s.tmpRLNDBPath()) rlnInstance, rootTracker, err := GetRLNInstanceAndRootTracker(s.tmpRLNDBPath())
s.Require().NoError(err) s.Require().NoError(err)
// mount the rln relay protocol in the on-chain/dynamic mode // mount the rln relay protocol in the on-chain/dynamic mode
gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rlnInstance, rootTracker, utils.Logger()) gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, &membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rlnInstance, rootTracker, utils.Logger())
s.Require().NoError(err) s.Require().NoError(err)
rlnRelay := New(group_manager.Details{ rlnRelay := New(group_manager.Details{
@ -275,7 +275,7 @@ func (s *WakuRLNRelayDynamicSuite) TestCorrectRegistrationOfPeers() {
// mount the rln relay protocol in the on-chain/dynamic mode // mount the rln relay protocol in the on-chain/dynamic mode
rootInstance, rootTracker, err := GetRLNInstanceAndRootTracker(s.tmpRLNDBPath()) rootInstance, rootTracker, err := GetRLNInstanceAndRootTracker(s.tmpRLNDBPath())
s.Require().NoError(err) s.Require().NoError(err)
gm1, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipGroupIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rootInstance, rootTracker, utils.Logger()) gm1, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, &membershipGroupIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, rootInstance, rootTracker, utils.Logger())
s.Require().NoError(err) s.Require().NoError(err)
rlnRelay1 := New(group_manager.Details{ rlnRelay1 := New(group_manager.Details{
@ -299,7 +299,7 @@ func (s *WakuRLNRelayDynamicSuite) TestCorrectRegistrationOfPeers() {
// mount the rln relay protocol in the on-chain/dynamic mode // mount the rln relay protocol in the on-chain/dynamic mode
rootInstance, rootTracker, err = GetRLNInstanceAndRootTracker(s.tmpRLNDBPath()) rootInstance, rootTracker, err = GetRLNInstanceAndRootTracker(s.tmpRLNDBPath())
s.Require().NoError(err) s.Require().NoError(err)
gm2, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipGroupIndex, appKeystore2, keystorePassword, prometheus.DefaultRegisterer, rootInstance, rootTracker, utils.Logger()) gm2, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, &membershipGroupIndex, appKeystore2, keystorePassword, prometheus.DefaultRegisterer, rootInstance, rootTracker, utils.Logger())
s.Require().NoError(err) s.Require().NoError(err)
rlnRelay2 := New(group_manager.Details{ rlnRelay2 := New(group_manager.Details{