Skip to content

Commit

Permalink
feat: use rln registry contract
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-ramos committed Sep 4, 2023
1 parent ab3f21f commit 5fcfbb9
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 147 deletions.
21 changes: 5 additions & 16 deletions cmd/waku/rlngenerate/command_rln.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/ethclient"
cli "github.com/urfave/cli/v2"
"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/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-zerokit-rln/rln"
"go.uber.org/zap"
Expand Down Expand Up @@ -46,22 +45,12 @@ var Command = cli.Command{
}

func execute(ctx context.Context) error {
ethClient, err := ethclient.Dial(options.ETHClientAddress)
if err != nil {
return err
}

rlnInstance, err := rln.NewRLN()
if err != nil {
return err
}

chainID, err := ethClient.ChainID(ctx)
if err != nil {
return err
}

rlnContract, err := contracts.NewRLN(options.MembershipContractAddress, ethClient)
web3Config, err := web3.BuildConfig(ctx, options.ETHClientAddress, options.MembershipContractAddress)
if err != nil {
return err
}
Expand All @@ -74,14 +63,14 @@ func execute(ctx context.Context) error {
}

// 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 {
return err
}

// TODO: clean private key from memory

err = persistCredentials(identityCredential, membershipIndex, chainID)
err = persistCredentials(identityCredential, membershipIndex, web3Config.ChainID)
if err != nil {
return err
}
Expand All @@ -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))
}

ethClient.Close()
web3Config.ETHClient.Close()

return nil
}
Expand Down
19 changes: 9 additions & 10 deletions cmd/waku/rlngenerate/web3.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"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"
"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})
}

Expand Down Expand Up @@ -70,28 +69,28 @@ func buildTransactor(ctx context.Context, membershipFee *big.Int, chainID *big.I
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
membershipFee, err := getMembershipFee(ctx, rlnContract)
membershipFee, err := getMembershipFee(ctx, web3Config.RLNContract)
if err != nil {
return 0, err
}

auth, err := buildTransactor(ctx, membershipFee, chainID)
auth, err := buildTransactor(ctx, membershipFee, web3Config.ChainID)
if err != nil {
return 0, err
}

log.Debug("registering an id commitment", zap.Binary("idComm", idComm[:]))

// 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 {
return 0, fmt.Errorf("transaction error: %w", err)
}

explorerURL := ""
switch chainID.Int64() {
switch web3Config.ChainID.Int64() {
case 1:
explorerURL = "https://etherscan.io"
case 5:
Expand All @@ -108,7 +107,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con

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 {
return 0, fmt.Errorf("transaction error: %w", err)
}
Expand All @@ -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
evt, err := rlnContract.ParseMemberRegistered(*txReceipt.Logs[0])
evt, err := web3Config.RLNContract.ParseMemberRegistered(*txReceipt.Logs[0])
if err != nil {
return 0, err
}
Expand Down
51 changes: 17 additions & 34 deletions waku/v2/protocol/rln/group_manager/dynamic/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/prometheus/client_golang/prometheus"
"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"
"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"
om "github.com/wk8/go-ordered-map"
"go.uber.org/zap"
Expand All @@ -38,17 +38,11 @@ type DynamicGroupManager struct {
identityCredential *rln.IdentityCredential
membershipIndex rln.MembershipIndex

membershipContractAddress common.Address
ethClientAddress string
ethClient *ethclient.Client

web3Config *web3.Config
lastBlockProcessed uint64

eventHandler RegistrationEventHandler

chainId *big.Int
rlnContract *contracts.RLN

appKeystore *keystore.AppKeystore
keystorePassword string

Expand Down Expand Up @@ -99,14 +93,14 @@ func handler(gm *DynamicGroupManager, events []*contracts.RLNMemberRegistered) e
gm.lastBlockProcessed = lastBlockProcessed
err = gm.SetMetadata(RLNMetadata{
LastProcessedBlock: gm.lastBlockProcessed,
ChainID: gm.chainId,
ContractAddress: gm.membershipContractAddress,
ChainID: gm.web3Config.ChainID,
ContractAddress: gm.web3Config.RegistryContract.Address,
})
if err != nil {
// this is not a fatal error, hence we don't raise an exception
gm.log.Warn("failed to persist rln metadata", zap.Error(err))
} 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
Expand All @@ -126,19 +120,18 @@ func NewDynamicGroupManager(
log = log.Named("rln-dynamic")

return &DynamicGroupManager{
membershipIndex: membershipIndex,
membershipContractAddress: memContractAddr,
ethClientAddress: ethClientAddr,
eventHandler: handler,
appKeystore: appKeystore,
keystorePassword: keystorePassword,
log: log,
metrics: newMetrics(reg),
membershipIndex: membershipIndex,
web3Config: web3.NewConfig(ethClientAddr, memContractAddr),
eventHandler: handler,
appKeystore: appKeystore,
keystorePassword: keystorePassword,
log: log,
metrics: newMetrics(reg),
}, nil
}

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 {
Expand All @@ -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")

backend, err := ethclient.Dial(gm.ethClientAddress)
err := gm.web3Config.Build(ctx)
if err != nil {
return err
}
gm.ethClient = backend

gm.rln = rlnInstance
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
_, err = gm.getMembershipFee(ctx)
if err != nil {
Expand All @@ -194,7 +176,7 @@ func (gm *DynamicGroupManager) loadCredential() error {
credentials, err := gm.appKeystore.GetMembershipCredentials(
gm.keystorePassword,
gm.membershipIndex,
keystore.NewMembershipContractInfo(gm.chainId, gm.membershipContractAddress))
keystore.NewMembershipContractInfo(gm.web3Config.ChainID, gm.web3Config.RegistryContract.Address))
if err != nil {
return err
}
Expand Down Expand Up @@ -281,7 +263,8 @@ func (gm *DynamicGroupManager) Stop() error {
if err != nil {
return err
}
gm.ethClient.Close()

gm.web3Config.ETHClient.Close()

gm.wg.Wait()

Expand Down
13 changes: 8 additions & 5 deletions waku/v2/protocol/rln/group_manager/dynamic/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"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/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-zerokit-rln/rln"
)
Expand Down Expand Up @@ -40,11 +41,13 @@ func TestHandler(t *testing.T) {
_ = ctx

gm := &DynamicGroupManager{
rln: rlnInstance,
log: utils.Logger(),
cancel: cancel,
wg: sync.WaitGroup{},
chainId: big.NewInt(1),
rln: rlnInstance,
log: utils.Logger(),
cancel: cancel,
wg: sync.WaitGroup{},
web3Config: &web3.Config{
ChainID: big.NewInt(1),
},
rootTracker: rootTracker,
metrics: newMetrics(prometheus.DefaultRegisterer),
}
Expand Down
18 changes: 9 additions & 9 deletions waku/v2/protocol/rln/group_manager/dynamic/web3.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,46 +26,46 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
if err != nil {
gm.log.Warn("could not load last processed block from metadata. Starting onchain sync from scratch", zap.Error(err))
} else {
if gm.chainId.Uint64() != metadata.ChainID.Uint64() {
if gm.web3Config.ChainID.Cmp(metadata.ChainID) != 0 {
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")
}

fromBlock = metadata.LastProcessedBlock
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 {
return err
}

errCh := make(chan error)

gm.wg.Add(1)
go gm.watchNewEvents(ctx, gm.rlnContract, handler, gm.log, errCh)
go gm.watchNewEvents(ctx, handler, gm.log, 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)
if err != nil {
return err
}
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()

// Watch for new events
firstErr := true
headerCh := make(chan *types.Header)
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 == rpc.ErrNotificationsUnsupported {
err = errors.New("notifications not supported. The node must support websockets")
Expand Down Expand Up @@ -123,7 +123,7 @@ func (gm *DynamicGroupManager) getEvents(ctx context.Context, from uint64, to *u

toBlock := to
if to == nil {
block, err := gm.ethClient.BlockByNumber(ctx, nil)
block, err := gm.web3Config.ETHClient.BlockByNumber(ctx, nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -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) {
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 {
return nil, err
}
Expand Down
Loading

0 comments on commit 5fcfbb9

Please sign in to comment.