mirror of https://github.com/status-im/go-waku.git
feat: use rln registry contract
This commit is contained in:
parent
ab3f21f209
commit
5fcfbb9897
|
@ -9,12 +9,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
|
||||||
cli "github.com/urfave/cli/v2"
|
cli "github.com/urfave/cli/v2"
|
||||||
"github.com/waku-org/go-waku/logging"
|
"github.com/waku-org/go-waku/logging"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -46,22 +45,12 @@ var Command = cli.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute(ctx context.Context) error {
|
func execute(ctx context.Context) error {
|
||||||
ethClient, err := ethclient.Dial(options.ETHClientAddress)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rlnInstance, err := rln.NewRLN()
|
rlnInstance, err := rln.NewRLN()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
chainID, err := ethClient.ChainID(ctx)
|
web3Config, err := web3.BuildConfig(ctx, options.ETHClientAddress, options.MembershipContractAddress)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rlnContract, err := contracts.NewRLN(options.MembershipContractAddress, ethClient)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -74,14 +63,14 @@ func execute(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the rln-relay peer to the membership contract
|
// register the rln-relay peer to the membership contract
|
||||||
membershipIndex, err := register(ctx, ethClient, rlnContract, identityCredential.IDCommitment, chainID)
|
membershipIndex, err := register(ctx, web3Config, identityCredential.IDCommitment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clean private key from memory
|
// TODO: clean private key from memory
|
||||||
|
|
||||||
err = persistCredentials(identityCredential, membershipIndex, chainID)
|
err = persistCredentials(identityCredential, membershipIndex, web3Config.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -98,7 +87,7 @@ func execute(ctx context.Context) error {
|
||||||
logger.Info("registered credentials into the membership contract", logging.HexString("idCommitment", identityCredential.IDCommitment[:]), zap.Uint("index", membershipIndex))
|
logger.Info("registered credentials into the membership contract", logging.HexString("idCommitment", identityCredential.IDCommitment[:]), zap.Uint("index", membershipIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
ethClient.Close()
|
web3Config.ETHClient.Close()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,14 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/waku-org/go-waku/logging"
|
"github.com/waku-org/go-waku/logging"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getMembershipFee(ctx context.Context, rlnContract *contracts.RLN) (*big.Int, error) {
|
func getMembershipFee(ctx context.Context, rlnContract web3.RLNContract) (*big.Int, error) {
|
||||||
return rlnContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
|
return rlnContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,14 +69,14 @@ func buildTransactor(ctx context.Context, membershipFee *big.Int, chainID *big.I
|
||||||
return auth, nil
|
return auth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *contracts.RLN, idComm rln.IDCommitment, chainID *big.Int) (rln.MembershipIndex, error) {
|
func register(ctx context.Context, web3Config *web3.Config, idComm rln.IDCommitment) (rln.MembershipIndex, error) {
|
||||||
// check if the contract exists by calling a static function
|
// check if the contract exists by calling a static function
|
||||||
membershipFee, err := getMembershipFee(ctx, rlnContract)
|
membershipFee, err := getMembershipFee(ctx, web3Config.RLNContract)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
auth, err := buildTransactor(ctx, membershipFee, chainID)
|
auth, err := buildTransactor(ctx, membershipFee, web3Config.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -85,13 +84,13 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
|
||||||
log.Debug("registering an id commitment", zap.Binary("idComm", idComm[:]))
|
log.Debug("registering an id commitment", zap.Binary("idComm", idComm[:]))
|
||||||
|
|
||||||
// registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
// registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||||
tx, err := rlnContract.Register(auth, rln.Bytes32ToBigInt(idComm))
|
tx, err := web3Config.RegistryContract.Register(auth, web3Config.RLNContract.StorageIndex, rln.Bytes32ToBigInt(idComm))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("transaction error: %w", err)
|
return 0, fmt.Errorf("transaction error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
explorerURL := ""
|
explorerURL := ""
|
||||||
switch chainID.Int64() {
|
switch web3Config.ChainID.Int64() {
|
||||||
case 1:
|
case 1:
|
||||||
explorerURL = "https://etherscan.io"
|
explorerURL = "https://etherscan.io"
|
||||||
case 5:
|
case 5:
|
||||||
|
@ -108,7 +107,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
|
||||||
|
|
||||||
logger.Warn("waiting for transaction to be mined...")
|
logger.Warn("waiting for transaction to be mined...")
|
||||||
|
|
||||||
txReceipt, err := bind.WaitMined(ctx, ethClient, tx)
|
txReceipt, err := bind.WaitMined(ctx, web3Config.ETHClient, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("transaction error: %w", err)
|
return 0, fmt.Errorf("transaction error: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +117,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
|
||||||
}
|
}
|
||||||
|
|
||||||
// the receipt topic holds the hash of signature of the raised events
|
// the receipt topic holds the hash of signature of the raised events
|
||||||
evt, err := rlnContract.ParseMemberRegistered(*txReceipt.Logs[0])
|
evt, err := web3Config.RLNContract.ParseMemberRegistered(*txReceipt.Logs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/waku-org/go-waku/logging"
|
"github.com/waku-org/go-waku/logging"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
om "github.com/wk8/go-ordered-map"
|
om "github.com/wk8/go-ordered-map"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -38,17 +38,11 @@ type DynamicGroupManager struct {
|
||||||
identityCredential *rln.IdentityCredential
|
identityCredential *rln.IdentityCredential
|
||||||
membershipIndex rln.MembershipIndex
|
membershipIndex rln.MembershipIndex
|
||||||
|
|
||||||
membershipContractAddress common.Address
|
web3Config *web3.Config
|
||||||
ethClientAddress string
|
|
||||||
ethClient *ethclient.Client
|
|
||||||
|
|
||||||
lastBlockProcessed uint64
|
lastBlockProcessed uint64
|
||||||
|
|
||||||
eventHandler RegistrationEventHandler
|
eventHandler RegistrationEventHandler
|
||||||
|
|
||||||
chainId *big.Int
|
|
||||||
rlnContract *contracts.RLN
|
|
||||||
|
|
||||||
appKeystore *keystore.AppKeystore
|
appKeystore *keystore.AppKeystore
|
||||||
keystorePassword string
|
keystorePassword string
|
||||||
|
|
||||||
|
@ -99,14 +93,14 @@ func handler(gm *DynamicGroupManager, events []*contracts.RLNMemberRegistered) e
|
||||||
gm.lastBlockProcessed = lastBlockProcessed
|
gm.lastBlockProcessed = lastBlockProcessed
|
||||||
err = gm.SetMetadata(RLNMetadata{
|
err = gm.SetMetadata(RLNMetadata{
|
||||||
LastProcessedBlock: gm.lastBlockProcessed,
|
LastProcessedBlock: gm.lastBlockProcessed,
|
||||||
ChainID: gm.chainId,
|
ChainID: gm.web3Config.ChainID,
|
||||||
ContractAddress: gm.membershipContractAddress,
|
ContractAddress: gm.web3Config.RegistryContract.Address,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// this is not a fatal error, hence we don't raise an exception
|
// this is not a fatal error, hence we don't raise an exception
|
||||||
gm.log.Warn("failed to persist rln metadata", zap.Error(err))
|
gm.log.Warn("failed to persist rln metadata", zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
gm.log.Debug("rln metadata persisted", zap.Uint64("lastProcessedBlock", gm.lastBlockProcessed), zap.Uint64("chainID", gm.chainId.Uint64()), logging.HexBytes("contractAddress", gm.membershipContractAddress[:]))
|
gm.log.Debug("rln metadata persisted", zap.Uint64("lastProcessedBlock", gm.lastBlockProcessed), zap.Uint64("chainID", gm.web3Config.ChainID.Uint64()), logging.HexBytes("contractAddress", gm.web3Config.RegistryContract.Address.Bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -126,19 +120,18 @@ func NewDynamicGroupManager(
|
||||||
log = log.Named("rln-dynamic")
|
log = log.Named("rln-dynamic")
|
||||||
|
|
||||||
return &DynamicGroupManager{
|
return &DynamicGroupManager{
|
||||||
membershipIndex: membershipIndex,
|
membershipIndex: membershipIndex,
|
||||||
membershipContractAddress: memContractAddr,
|
web3Config: web3.NewConfig(ethClientAddr, memContractAddr),
|
||||||
ethClientAddress: ethClientAddr,
|
eventHandler: handler,
|
||||||
eventHandler: handler,
|
appKeystore: appKeystore,
|
||||||
appKeystore: appKeystore,
|
keystorePassword: keystorePassword,
|
||||||
keystorePassword: keystorePassword,
|
log: log,
|
||||||
log: log,
|
metrics: newMetrics(reg),
|
||||||
metrics: newMetrics(reg),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *DynamicGroupManager) getMembershipFee(ctx context.Context) (*big.Int, error) {
|
func (gm *DynamicGroupManager) getMembershipFee(ctx context.Context) (*big.Int, error) {
|
||||||
return gm.rlnContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
|
return gm.web3Config.RLNContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *DynamicGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN, rootTracker *group_manager.MerkleRootTracker) error {
|
func (gm *DynamicGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN, rootTracker *group_manager.MerkleRootTracker) error {
|
||||||
|
@ -151,25 +144,14 @@ func (gm *DynamicGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN,
|
||||||
|
|
||||||
gm.log.Info("mounting rln-relay in on-chain/dynamic mode")
|
gm.log.Info("mounting rln-relay in on-chain/dynamic mode")
|
||||||
|
|
||||||
backend, err := ethclient.Dial(gm.ethClientAddress)
|
err := gm.web3Config.Build(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gm.ethClient = backend
|
|
||||||
|
|
||||||
gm.rln = rlnInstance
|
gm.rln = rlnInstance
|
||||||
gm.rootTracker = rootTracker
|
gm.rootTracker = rootTracker
|
||||||
|
|
||||||
gm.chainId, err = backend.ChainID(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
gm.rlnContract, err = contracts.NewRLN(gm.membershipContractAddress, backend)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the contract exists by calling a static function
|
// check if the contract exists by calling a static function
|
||||||
_, err = gm.getMembershipFee(ctx)
|
_, err = gm.getMembershipFee(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -194,7 +176,7 @@ func (gm *DynamicGroupManager) loadCredential() error {
|
||||||
credentials, err := gm.appKeystore.GetMembershipCredentials(
|
credentials, err := gm.appKeystore.GetMembershipCredentials(
|
||||||
gm.keystorePassword,
|
gm.keystorePassword,
|
||||||
gm.membershipIndex,
|
gm.membershipIndex,
|
||||||
keystore.NewMembershipContractInfo(gm.chainId, gm.membershipContractAddress))
|
keystore.NewMembershipContractInfo(gm.web3Config.ChainID, gm.web3Config.RegistryContract.Address))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -281,7 +263,8 @@ func (gm *DynamicGroupManager) Stop() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gm.ethClient.Close()
|
|
||||||
|
gm.web3Config.ETHClient.Close()
|
||||||
|
|
||||||
gm.wg.Wait()
|
gm.wg.Wait()
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
)
|
)
|
||||||
|
@ -40,11 +41,13 @@ func TestHandler(t *testing.T) {
|
||||||
_ = ctx
|
_ = ctx
|
||||||
|
|
||||||
gm := &DynamicGroupManager{
|
gm := &DynamicGroupManager{
|
||||||
rln: rlnInstance,
|
rln: rlnInstance,
|
||||||
log: utils.Logger(),
|
log: utils.Logger(),
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
wg: sync.WaitGroup{},
|
wg: sync.WaitGroup{},
|
||||||
chainId: big.NewInt(1),
|
web3Config: &web3.Config{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
},
|
||||||
rootTracker: rootTracker,
|
rootTracker: rootTracker,
|
||||||
metrics: newMetrics(prometheus.DefaultRegisterer),
|
metrics: newMetrics(prometheus.DefaultRegisterer),
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,11 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gm.log.Warn("could not load last processed block from metadata. Starting onchain sync from scratch", zap.Error(err))
|
gm.log.Warn("could not load last processed block from metadata. Starting onchain sync from scratch", zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
if gm.chainId.Uint64() != metadata.ChainID.Uint64() {
|
if gm.web3Config.ChainID.Cmp(metadata.ChainID) != 0 {
|
||||||
return errors.New("persisted data: chain id mismatch")
|
return errors.New("persisted data: chain id mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(gm.membershipContractAddress[:], metadata.ContractAddress[:]) {
|
if !bytes.Equal(gm.web3Config.RegistryContract.Address.Bytes(), metadata.ContractAddress.Bytes()) {
|
||||||
return errors.New("persisted data: contract address mismatch")
|
return errors.New("persisted data: contract address mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
|
||||||
gm.log.Info("resuming onchain sync", zap.Uint64("fromBlock", fromBlock))
|
gm.log.Info("resuming onchain sync", zap.Uint64("fromBlock", fromBlock))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gm.loadOldEvents(ctx, gm.rlnContract, fromBlock, handler)
|
err = gm.loadOldEvents(ctx, fromBlock, handler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
|
|
||||||
gm.wg.Add(1)
|
gm.wg.Add(1)
|
||||||
go gm.watchNewEvents(ctx, gm.rlnContract, handler, gm.log, errCh)
|
go gm.watchNewEvents(ctx, handler, gm.log, errCh)
|
||||||
return <-errCh
|
return <-errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *contracts.RLN, fromBlock uint64, handler RegistrationEventHandler) error {
|
func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, fromBlock uint64, handler RegistrationEventHandler) error {
|
||||||
events, err := gm.getEvents(ctx, fromBlock, nil)
|
events, err := gm.getEvents(ctx, fromBlock, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -58,14 +58,14 @@ func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *c
|
||||||
return handler(gm, events)
|
return handler(gm, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *DynamicGroupManager) watchNewEvents(ctx context.Context, rlnContract *contracts.RLN, handler RegistrationEventHandler, log *zap.Logger, errCh chan<- error) {
|
func (gm *DynamicGroupManager) watchNewEvents(ctx context.Context, handler RegistrationEventHandler, log *zap.Logger, errCh chan<- error) {
|
||||||
defer gm.wg.Done()
|
defer gm.wg.Done()
|
||||||
|
|
||||||
// Watch for new events
|
// Watch for new events
|
||||||
firstErr := true
|
firstErr := true
|
||||||
headerCh := make(chan *types.Header)
|
headerCh := make(chan *types.Header)
|
||||||
subs := event.Resubscribe(2*time.Second, func(ctx context.Context) (event.Subscription, error) {
|
subs := event.Resubscribe(2*time.Second, func(ctx context.Context) (event.Subscription, error) {
|
||||||
s, err := gm.ethClient.SubscribeNewHead(ctx, headerCh)
|
s, err := gm.web3Config.ETHClient.SubscribeNewHead(ctx, headerCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == rpc.ErrNotificationsUnsupported {
|
if err == rpc.ErrNotificationsUnsupported {
|
||||||
err = errors.New("notifications not supported. The node must support websockets")
|
err = errors.New("notifications not supported. The node must support websockets")
|
||||||
|
@ -123,7 +123,7 @@ func (gm *DynamicGroupManager) getEvents(ctx context.Context, from uint64, to *u
|
||||||
|
|
||||||
toBlock := to
|
toBlock := to
|
||||||
if to == nil {
|
if to == nil {
|
||||||
block, err := gm.ethClient.BlockByNumber(ctx, nil)
|
block, err := gm.web3Config.ETHClient.BlockByNumber(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ func (gm *DynamicGroupManager) getEvents(ctx context.Context, from uint64, to *u
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *DynamicGroupManager) fetchEvents(ctx context.Context, from uint64, to *uint64) ([]*contracts.RLNMemberRegistered, error) {
|
func (gm *DynamicGroupManager) fetchEvents(ctx context.Context, from uint64, to *uint64) ([]*contracts.RLNMemberRegistered, error) {
|
||||||
logIterator, err := gm.rlnContract.FilterMemberRegistered(&bind.FilterOpts{Start: from, End: to, Context: ctx})
|
logIterator, err := gm.web3Config.RLNContract.FilterMemberRegistered(&bind.FilterOpts{Start: from, End: to, Context: ctx})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@ package rln
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/waku-org/go-zerokit-rln/rln"
|
"github.com/waku-org/go-zerokit-rln/rln"
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
@ -25,11 +27,11 @@ import (
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/web3"
|
||||||
"github.com/waku-org/go-waku/waku/v2/timesource"
|
"github.com/waku-org/go-waku/waku/v2/timesource"
|
||||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var membershipFee = big.NewInt(1000000000000000) // wei - 0.001 eth
|
|
||||||
const keystorePassword = "test"
|
const keystorePassword = "test"
|
||||||
|
|
||||||
func TestWakuRLNRelayDynamicSuite(t *testing.T) {
|
func TestWakuRLNRelayDynamicSuite(t *testing.T) {
|
||||||
|
@ -38,29 +40,27 @@ func TestWakuRLNRelayDynamicSuite(t *testing.T) {
|
||||||
|
|
||||||
type WakuRLNRelayDynamicSuite struct {
|
type WakuRLNRelayDynamicSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
web3Config *web3.Config
|
||||||
clientAddr string
|
u1PrivKey *ecdsa.PrivateKey
|
||||||
|
u2PrivKey *ecdsa.PrivateKey
|
||||||
backend *ethclient.Client
|
|
||||||
chainID *big.Int
|
|
||||||
rlnAddr common.Address
|
|
||||||
rlnContract *contracts.RLN
|
|
||||||
|
|
||||||
u1PrivKey *ecdsa.PrivateKey
|
|
||||||
u2PrivKey *ecdsa.PrivateKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: on teardown, remove credentials
|
func TempFileName(prefix, suffix string) string {
|
||||||
|
randBytes := make([]byte, 16)
|
||||||
|
rand.Read(randBytes)
|
||||||
|
return filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes)+suffix)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *WakuRLNRelayDynamicSuite) SetupTest() {
|
func (s *WakuRLNRelayDynamicSuite) SetupTest() {
|
||||||
|
|
||||||
s.clientAddr = os.Getenv("GANACHE_NETWORK_RPC_URL")
|
clientAddr := os.Getenv("GANACHE_NETWORK_RPC_URL")
|
||||||
if s.clientAddr == "" {
|
if clientAddr == "" {
|
||||||
s.clientAddr = "ws://localhost:8545"
|
clientAddr = "ws://localhost:8545"
|
||||||
}
|
}
|
||||||
|
|
||||||
backend, err := ethclient.Dial(s.clientAddr)
|
backend, err := ethclient.Dial(clientAddr)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
chainID, err := backend.ChainID(context.TODO())
|
chainID, err := backend.ChainID(context.TODO())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -72,9 +72,6 @@ func (s *WakuRLNRelayDynamicSuite) SetupTest() {
|
||||||
s.u2PrivKey, err = crypto.ToECDSA(common.FromHex("0xa00da43843ad6b5161ddbace48f293ac3f82f8a8257af34de4c32900bb6e9a97"))
|
s.u2PrivKey, err = crypto.ToECDSA(common.FromHex("0xa00da43843ad6b5161ddbace48f293ac3f82f8a8257af34de4c32900bb6e9a97"))
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.backend = backend
|
|
||||||
s.chainID = chainID
|
|
||||||
|
|
||||||
// Deploying contracts
|
// Deploying contracts
|
||||||
auth, err := bind.NewKeyedTransactorWithChainID(s.u1PrivKey, chainID)
|
auth, err := bind.NewKeyedTransactorWithChainID(s.u1PrivKey, chainID)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -82,18 +79,21 @@ func (s *WakuRLNRelayDynamicSuite) SetupTest() {
|
||||||
poseidonHasherAddr, _, _, err := contracts.DeployPoseidonHasher(auth, backend)
|
poseidonHasherAddr, _, _, err := contracts.DeployPoseidonHasher(auth, backend)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
rlnAddr, _, rlnContract, err := contracts.DeployRLN(auth, backend, membershipFee, big.NewInt(20), poseidonHasherAddr)
|
registryAddress, tx, rlnRegistry, err := contracts.DeployRLNRegistry(auth, backend, poseidonHasherAddr)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
txReceipt, err := bind.WaitMined(context.TODO(), backend, tx)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
||||||
|
|
||||||
s.rlnAddr = rlnAddr
|
tx, err = rlnRegistry.NewStorage(auth)
|
||||||
s.rlnContract = rlnContract
|
s.Require().NoError(err)
|
||||||
}
|
txReceipt, err = bind.WaitMined(context.TODO(), backend, tx)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
||||||
|
|
||||||
func (s *WakuRLNRelayDynamicSuite) removeCredentials(path string) {
|
s.web3Config = web3.NewConfig(clientAddr, registryAddress)
|
||||||
err := os.Remove(path)
|
err = s.web3Config.Build(context.TODO())
|
||||||
if err != nil {
|
s.Require().NoError(err)
|
||||||
utils.Logger().Warn("could not remove credentials", zap.String("path", path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WakuRLNRelayDynamicSuite) generateCredentials(rlnInstance *rln.RLN) *rln.IdentityCredential {
|
func (s *WakuRLNRelayDynamicSuite) generateCredentials(rlnInstance *rln.RLN) *rln.IdentityCredential {
|
||||||
|
@ -103,21 +103,22 @@ func (s *WakuRLNRelayDynamicSuite) generateCredentials(rlnInstance *rln.RLN) *rl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WakuRLNRelayDynamicSuite) register(appKeystore *keystore.AppKeystore, identityCredential *rln.IdentityCredential, privKey *ecdsa.PrivateKey) rln.MembershipIndex {
|
func (s *WakuRLNRelayDynamicSuite) register(appKeystore *keystore.AppKeystore, identityCredential *rln.IdentityCredential, privKey *ecdsa.PrivateKey) rln.MembershipIndex {
|
||||||
|
membershipFee, err := s.web3Config.RLNContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: context.TODO()})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
auth, err := bind.NewKeyedTransactorWithChainID(privKey, s.chainID)
|
auth, err := bind.NewKeyedTransactorWithChainID(privKey, s.web3Config.ChainID)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
auth.Value = membershipFee
|
auth.Value = membershipFee
|
||||||
auth.Context = context.TODO()
|
auth.Context = context.TODO()
|
||||||
|
tx, err := s.web3Config.RegistryContract.Register(auth, s.web3Config.RLNContract.StorageIndex, rln.Bytes32ToBigInt(identityCredential.IDCommitment))
|
||||||
tx, err := s.rlnContract.Register(auth, rln.Bytes32ToBigInt(identityCredential.IDCommitment))
|
|
||||||
s.Require().NoError(err)
|
|
||||||
txReceipt, err := bind.WaitMined(context.TODO(), s.backend, tx)
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
txReceipt, err := bind.WaitMined(context.TODO(), s.web3Config.ETHClient, tx)
|
||||||
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
||||||
|
|
||||||
evt, err := s.rlnContract.ParseMemberRegistered(*txReceipt.Logs[0])
|
evt, err := s.web3Config.RLNContract.ParseMemberRegistered(*txReceipt.Logs[0])
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
membershipIndex := rln.MembershipIndex(uint(evt.Index.Int64()))
|
membershipIndex := rln.MembershipIndex(uint(evt.Index.Int64()))
|
||||||
|
@ -125,7 +126,7 @@ func (s *WakuRLNRelayDynamicSuite) register(appKeystore *keystore.AppKeystore, i
|
||||||
membershipCredential := keystore.MembershipCredentials{
|
membershipCredential := keystore.MembershipCredentials{
|
||||||
IdentityCredential: identityCredential,
|
IdentityCredential: identityCredential,
|
||||||
TreeIndex: membershipIndex,
|
TreeIndex: membershipIndex,
|
||||||
MembershipContractInfo: keystore.NewMembershipContractInfo(s.chainID, s.rlnAddr),
|
MembershipContractInfo: keystore.NewMembershipContractInfo(s.web3Config.ChainID, s.web3Config.RegistryContract.Address),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = appKeystore.AddMembershipCredentials(membershipCredential, keystorePassword)
|
err = appKeystore.AddMembershipCredentials(membershipCredential, keystorePassword)
|
||||||
|
@ -143,14 +144,12 @@ func (s *WakuRLNRelayDynamicSuite) TestDynamicGroupManagement() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
u1Credentials := s.generateCredentials(rlnInstance)
|
u1Credentials := s.generateCredentials(rlnInstance)
|
||||||
keystorePath1 := "./test_onchain.json"
|
appKeystore, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore, err := keystore.New(keystorePath1, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
membershipIndex := s.register(appKeystore, u1Credentials, s.u1PrivKey)
|
membershipIndex := s.register(appKeystore, u1Credentials, s.u1PrivKey)
|
||||||
defer s.removeCredentials(keystorePath1)
|
|
||||||
|
|
||||||
gm, err := dynamic.NewDynamicGroupManager(s.clientAddr, s.rlnAddr, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// initialize the WakuRLNRelay
|
// initialize the WakuRLNRelay
|
||||||
|
@ -166,12 +165,10 @@ func (s *WakuRLNRelayDynamicSuite) TestDynamicGroupManagement() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
u2Credentials := s.generateCredentials(rlnInstance)
|
u2Credentials := s.generateCredentials(rlnInstance)
|
||||||
keystorePath2 := "./test_onchain2.json"
|
appKeystore2, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore2, err := keystore.New(keystorePath2, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
membershipIndex = s.register(appKeystore2, u2Credentials, s.u2PrivKey)
|
membershipIndex = s.register(appKeystore2, u2Credentials, s.u2PrivKey)
|
||||||
defer s.removeCredentials(keystorePath2)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
@ -189,24 +186,25 @@ func (s *WakuRLNRelayDynamicSuite) TestInsertKeyMembershipContract() {
|
||||||
credentials2 := s.generateCredentials(rlnInstance)
|
credentials2 := s.generateCredentials(rlnInstance)
|
||||||
credentials3 := s.generateCredentials(rlnInstance)
|
credentials3 := s.generateCredentials(rlnInstance)
|
||||||
|
|
||||||
keystorePath1 := "./test_onchain.json"
|
appKeystore, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore, err := keystore.New(keystorePath1, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.register(appKeystore, credentials1, s.u1PrivKey)
|
s.register(appKeystore, credentials1, s.u1PrivKey)
|
||||||
defer s.removeCredentials(keystorePath1)
|
|
||||||
|
|
||||||
// Batch Register
|
// Batch Register
|
||||||
auth, err := bind.NewKeyedTransactorWithChainID(s.u2PrivKey, s.chainID)
|
auth, err := bind.NewKeyedTransactorWithChainID(s.u2PrivKey, s.web3Config.ChainID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
membershipFee, err := s.web3Config.RLNContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: context.TODO()})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
auth.Value = membershipFee.Mul(big.NewInt(2), membershipFee)
|
auth.Value = membershipFee.Mul(big.NewInt(2), membershipFee)
|
||||||
auth.Context = context.TODO()
|
auth.Context = context.TODO()
|
||||||
|
|
||||||
tx, err := s.rlnContract.RegisterBatch(auth, []*big.Int{rln.Bytes32ToBigInt(credentials2.IDCommitment), rln.Bytes32ToBigInt(credentials3.IDCommitment)})
|
tx, err := s.web3Config.RegistryContract.Register1(auth, s.web3Config.RLNContract.StorageIndex, []*big.Int{rln.Bytes32ToBigInt(credentials2.IDCommitment), rln.Bytes32ToBigInt(credentials3.IDCommitment)})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
txReceipt, err := bind.WaitMined(context.TODO(), s.backend, tx)
|
txReceipt, err := bind.WaitMined(context.TODO(), s.web3Config.ETHClient, tx)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
s.Require().Equal(txReceipt.Status, types.ReceiptStatusSuccessful)
|
||||||
}
|
}
|
||||||
|
@ -219,10 +217,7 @@ func (s *WakuRLNRelayDynamicSuite) TestMerkleTreeConstruction() {
|
||||||
credentials1 := s.generateCredentials(rlnInstance)
|
credentials1 := s.generateCredentials(rlnInstance)
|
||||||
credentials2 := s.generateCredentials(rlnInstance)
|
credentials2 := s.generateCredentials(rlnInstance)
|
||||||
|
|
||||||
err = rlnInstance.InsertMember(credentials1.IDCommitment)
|
err = rlnInstance.InsertMembers(1, []rln.IDCommitment{credentials1.IDCommitment, credentials2.IDCommitment})
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
err = rlnInstance.InsertMember(credentials2.IDCommitment)
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// get the Merkle root
|
// get the Merkle root
|
||||||
|
@ -230,21 +225,17 @@ func (s *WakuRLNRelayDynamicSuite) TestMerkleTreeConstruction() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// register the members to the contract
|
// register the members to the contract
|
||||||
keystorePath1 := "./test_onchain.json"
|
appKeystore, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore, err := keystore.New(keystorePath1, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
membershipIndex := s.register(appKeystore, credentials1, s.u1PrivKey)
|
membershipIndex := s.register(appKeystore, credentials1, s.u1PrivKey)
|
||||||
membershipIndex = s.register(appKeystore, credentials2, s.u1PrivKey)
|
membershipIndex = s.register(appKeystore, credentials2, s.u1PrivKey)
|
||||||
|
|
||||||
defer s.removeCredentials(keystorePath1)
|
|
||||||
|
|
||||||
// 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.clientAddr, s.rlnAddr, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
gm, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
||||||
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
rlnRelay, err := New(gm, "test-merkle-tree.db", timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
rlnRelay, err := New(gm, s.tmpRLNDBPath(), timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
err = rlnRelay.Start(context.TODO())
|
err = rlnRelay.Start(context.TODO())
|
||||||
|
@ -257,7 +248,6 @@ func (s *WakuRLNRelayDynamicSuite) TestMerkleTreeConstruction() {
|
||||||
// is expected to be the same as the calculatedRoot i.e., the one calculated outside of the mountRlnRelayDynamic proc
|
// is expected to be the same as the calculatedRoot i.e., the one calculated outside of the mountRlnRelayDynamic proc
|
||||||
calculatedRoot, err := rlnRelay.RLN.GetMerkleRoot()
|
calculatedRoot, err := rlnRelay.RLN.GetMerkleRoot()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Equal(expectedRoot, calculatedRoot)
|
s.Require().Equal(expectedRoot, calculatedRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,17 +260,15 @@ func (s *WakuRLNRelayDynamicSuite) TestCorrectRegistrationOfPeers() {
|
||||||
|
|
||||||
// Register credentials1 in contract and keystore1
|
// Register credentials1 in contract and keystore1
|
||||||
credentials1 := s.generateCredentials(rlnInstance)
|
credentials1 := s.generateCredentials(rlnInstance)
|
||||||
keystorePath1 := "./test_onchain.json"
|
appKeystore, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore, err := keystore.New(keystorePath1, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
membershipGroupIndex := s.register(appKeystore, credentials1, s.u1PrivKey)
|
membershipGroupIndex := s.register(appKeystore, credentials1, s.u1PrivKey)
|
||||||
defer s.removeCredentials(keystorePath1)
|
|
||||||
|
|
||||||
// mount the rln relay protocol in the on-chain/dynamic mode
|
// mount the rln relay protocol in the on-chain/dynamic mode
|
||||||
gm1, err := dynamic.NewDynamicGroupManager(s.clientAddr, s.rlnAddr, membershipGroupIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
gm1, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipGroupIndex, appKeystore, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
rlnRelay1, err := New(gm1, "test-correct-registration-1.db", timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
rlnRelay1, err := New(gm1, s.tmpRLNDBPath(), timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
err = rlnRelay1.Start(context.TODO())
|
err = rlnRelay1.Start(context.TODO())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -289,17 +277,16 @@ func (s *WakuRLNRelayDynamicSuite) TestCorrectRegistrationOfPeers() {
|
||||||
|
|
||||||
// Register credentials2 in contract and keystore2
|
// Register credentials2 in contract and keystore2
|
||||||
credentials2 := s.generateCredentials(rlnInstance)
|
credentials2 := s.generateCredentials(rlnInstance)
|
||||||
keystorePath2 := "./test_onchain2.json"
|
appKeystore2, err := keystore.New(s.tmpKeystorePath(), dynamic.RLNAppInfo, utils.Logger())
|
||||||
appKeystore2, err := keystore.New(keystorePath2, dynamic.RLNAppInfo, utils.Logger())
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
membershipGroupIndex = s.register(appKeystore2, credentials2, s.u2PrivKey)
|
membershipGroupIndex = s.register(appKeystore2, credentials2, s.u2PrivKey)
|
||||||
defer s.removeCredentials(keystorePath2)
|
|
||||||
|
|
||||||
// mount the rln relay protocol in the on-chain/dynamic mode
|
// mount the rln relay protocol in the on-chain/dynamic mode
|
||||||
gm2, err := dynamic.NewDynamicGroupManager(s.clientAddr, s.rlnAddr, membershipGroupIndex, appKeystore2, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
gm2, err := dynamic.NewDynamicGroupManager(s.web3Config.ETHClientAddress, s.web3Config.RegistryContract.Address, membershipGroupIndex, appKeystore2, keystorePassword, prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
rlnRelay2, err := New(gm2, "test-correct-registration-2.db", timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
rlnRelay2, err := New(gm2, s.tmpRLNDBPath(), timesource.NewDefaultClock(), prometheus.DefaultRegisterer, utils.Logger())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
err = rlnRelay2.Start(context.TODO())
|
err = rlnRelay2.Start(context.TODO())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -311,7 +298,18 @@ func (s *WakuRLNRelayDynamicSuite) TestCorrectRegistrationOfPeers() {
|
||||||
idx1 := rlnRelay1.groupManager.MembershipIndex()
|
idx1 := rlnRelay1.groupManager.MembershipIndex()
|
||||||
idx2 := rlnRelay2.groupManager.MembershipIndex()
|
idx2 := rlnRelay2.groupManager.MembershipIndex()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(rln.MembershipIndex(1), idx1)
|
||||||
s.Require().Equal(rln.MembershipIndex(0), idx1)
|
s.Require().Equal(rln.MembershipIndex(2), idx2)
|
||||||
s.Require().Equal(rln.MembershipIndex(1), idx2)
|
}
|
||||||
|
|
||||||
|
func (s *WakuRLNRelayDynamicSuite) tmpKeystorePath() string {
|
||||||
|
keystoreDir, err := os.MkdirTemp("", "keystore_dir")
|
||||||
|
s.Require().NoError(err)
|
||||||
|
return filepath.Join(keystoreDir, "keystore.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *WakuRLNRelayDynamicSuite) tmpRLNDBPath() string {
|
||||||
|
dbPath, err := os.MkdirTemp("", "rln_db")
|
||||||
|
s.Require().NoError(err)
|
||||||
|
return dbPath
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package web3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/rln/contracts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegistryContract contains an instance of the RLN Registry contract and its address
|
||||||
|
type RegistryContract struct {
|
||||||
|
*contracts.RLNRegistry
|
||||||
|
Address common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// RLNContract contains an instance of the RLN contract, its address and the storage index within the registry
|
||||||
|
// that represents this contract
|
||||||
|
type RLNContract struct {
|
||||||
|
*contracts.RLN
|
||||||
|
Address common.Address
|
||||||
|
StorageIndex uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config is a helper struct that contains attributes for interaction with RLN smart contracts
|
||||||
|
type Config struct {
|
||||||
|
configured bool
|
||||||
|
|
||||||
|
ETHClientAddress string
|
||||||
|
ETHClient *ethclient.Client
|
||||||
|
ChainID *big.Int
|
||||||
|
RegistryContract RegistryContract
|
||||||
|
RLNContract RLNContract
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfig creates an instance of web3 Config
|
||||||
|
func NewConfig(ethClientAddress string, registryAddress common.Address) *Config {
|
||||||
|
return &Config{
|
||||||
|
ETHClientAddress: ethClientAddress,
|
||||||
|
RegistryContract: RegistryContract{
|
||||||
|
Address: registryAddress,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildConfig returns an instance of Web3Config with all the required elements for interaction with the RLN smart contracts
|
||||||
|
func BuildConfig(ctx context.Context, ethClientAddress string, registryAddress common.Address) (*Config, error) {
|
||||||
|
ethClient, err := ethclient.Dial(ethClientAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
chainID, err := ethClient.ChainID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rlnRegistry, err := contracts.NewRLNRegistry(registryAddress, ethClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
storageIndex, err := rlnRegistry.UsingStorageIndex(&bind.CallOpts{Context: ctx})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rlnContractAddress, err := rlnRegistry.Storages(&bind.CallOpts{Context: ctx}, storageIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rlnContract, err := contracts.NewRLN(rlnContractAddress, ethClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Config{
|
||||||
|
configured: true,
|
||||||
|
ETHClientAddress: ethClientAddress,
|
||||||
|
ETHClient: ethClient,
|
||||||
|
ChainID: chainID,
|
||||||
|
RegistryContract: RegistryContract{
|
||||||
|
RLNRegistry: rlnRegistry,
|
||||||
|
Address: registryAddress,
|
||||||
|
},
|
||||||
|
RLNContract: RLNContract{
|
||||||
|
RLN: rlnContract,
|
||||||
|
Address: rlnContractAddress,
|
||||||
|
StorageIndex: storageIndex,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build sets up the Config object by instantiating the eth client and contracts
|
||||||
|
func (w *Config) Build(ctx context.Context) error {
|
||||||
|
if w.configured {
|
||||||
|
return errors.New("already configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
if w.ETHClientAddress == "" {
|
||||||
|
return errors.New("no eth client address")
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroAddr common.Address
|
||||||
|
if w.RegistryContract.Address == zeroAddr {
|
||||||
|
return errors.New("no registry contract address")
|
||||||
|
}
|
||||||
|
|
||||||
|
newW, err := BuildConfig(ctx, w.ETHClientAddress, w.RegistryContract.Address)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*w = *newW
|
||||||
|
w.configured = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue