feat: handle chain forks

This commit is contained in:
Richard Ramos 2023-04-12 17:53:23 -04:00 committed by RichΛrd
parent 5de3d9f619
commit c3ef173b2c
10 changed files with 362 additions and 94 deletions

View File

@ -28,7 +28,7 @@
]; ];
doCheck = false; doCheck = false;
# FIXME: This needs to be manually changed when updating modules. # FIXME: This needs to be manually changed when updating modules.
vendorSha256 = "sha256-NtaKb8b3Pg8iSWZp4x27yFyNlrJVqaChWNyJz3yO59g="; vendorSha256 = "sha256-17E63+sejYDLkYH43J02cE8K4JjTYoi+kpMyEt+diFU=";
# Fix for 'nix run' trying to execute 'go-waku'. # Fix for 'nix run' trying to execute 'go-waku'.
meta = { mainProgram = "waku"; }; meta = { mainProgram = "waku"; };
}; };

1
go.mod
View File

@ -39,6 +39,7 @@ require (
github.com/lib/pq v1.10.4 github.com/lib/pq v1.10.4
github.com/waku-org/go-noise v0.0.4 github.com/waku-org/go-noise v0.0.4
github.com/waku-org/go-zerokit-rln v0.1.12 github.com/waku-org/go-zerokit-rln v0.1.12
github.com/wk8/go-ordered-map v1.0.0
) )
require ( require (

2
go.sum
View File

@ -1577,6 +1577,8 @@ github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230331181847-cba74520bae9/go.
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8=
github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=

View File

@ -16,7 +16,7 @@ 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/keystore" "github.com/waku-org/go-waku/waku/v2/protocol/rln/keystore"
"github.com/waku-org/go-zerokit-rln/rln" "github.com/waku-org/go-zerokit-rln/rln"
r "github.com/waku-org/go-zerokit-rln/rln" om "github.com/wk8/go-ordered-map"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -49,7 +49,6 @@ type DynamicGroupManager struct {
chainId *big.Int chainId *big.Int
rlnContract *contracts.RLN rlnContract *contracts.RLN
membershipFee *big.Int membershipFee *big.Int
lastIndexLoaded int64
saveKeystore bool saveKeystore bool
keystorePath string keystorePath string
@ -58,6 +57,42 @@ type DynamicGroupManager struct {
rootTracker *group_manager.MerkleRootTracker rootTracker *group_manager.MerkleRootTracker
} }
func handler(gm *DynamicGroupManager, events []*contracts.RLNMemberRegistered) error {
toRemoveTable := om.New()
toInsertTable := om.New()
for _, event := range events {
if event.Raw.Removed {
var indexes []uint64
i_idx, ok := toRemoveTable.Get(event.Raw.BlockNumber)
if ok {
indexes = i_idx.([]uint64)
}
indexes = append(indexes, event.Index.Uint64())
toRemoveTable.Set(event.Raw.BlockNumber, indexes)
} else {
var eventsPerBlock []*contracts.RLNMemberRegistered
i_evt, ok := toInsertTable.Get(event.Raw.BlockNumber)
if ok {
eventsPerBlock = i_evt.([]*contracts.RLNMemberRegistered)
}
eventsPerBlock = append(eventsPerBlock, event)
toInsertTable.Set(event.Raw.BlockNumber, eventsPerBlock)
}
}
err := gm.RemoveMembers(toRemoveTable)
if err != nil {
return err
}
err = gm.InsertMembers(toInsertTable)
if err != nil {
return err
}
return nil
}
type RegistrationHandler = func(tx *types.Transaction) type RegistrationHandler = func(tx *types.Transaction)
func NewDynamicGroupManager( func NewDynamicGroupManager(
@ -89,7 +124,6 @@ func NewDynamicGroupManager(
ethClientAddress: ethClientAddr, ethClientAddress: ethClientAddr,
ethAccountPrivateKey: ethAccountPrivateKey, ethAccountPrivateKey: ethAccountPrivateKey,
registrationHandler: registrationHandler, registrationHandler: registrationHandler,
lastIndexLoaded: -1,
saveKeystore: saveKeystore, saveKeystore: saveKeystore,
keystorePath: path, keystorePath: path,
keystorePassword: password, keystorePassword: password,
@ -142,11 +176,6 @@ func (gm *DynamicGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN,
return err return err
} }
err = rootTracker.Sync()
if err != nil {
return err
}
if gm.keystorePassword != "" && gm.keystorePath != "" { if gm.keystorePassword != "" && gm.keystorePath != "" {
credentials, err := keystore.GetMembershipCredentials(gm.log, credentials, err := keystore.GetMembershipCredentials(gm.log,
gm.keystorePath, gm.keystorePath,
@ -200,10 +229,6 @@ func (gm *DynamicGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN,
return errors.New("no credentials available") return errors.New("no credentials available")
} }
handler := func(pubkey r.IDCommitment, index r.MembershipIndex) error {
return gm.InsertMember(pubkey)
}
if err = gm.HandleGroupUpdates(ctx, handler); err != nil { if err = gm.HandleGroupUpdates(ctx, handler); err != nil {
return err return err
} }
@ -239,18 +264,38 @@ func (gm *DynamicGroupManager) persistCredentials() error {
return nil return nil
} }
func (gm *DynamicGroupManager) InsertMember(pubkey rln.IDCommitment) error { func (gm *DynamicGroupManager) InsertMembers(toInsert *om.OrderedMap) error {
gm.log.Debug("a new key is added", zap.Binary("pubkey", pubkey[:])) for pair := toInsert.Oldest(); pair != nil; pair = pair.Next() {
// assuming all the members arrive in order events := pair.Value.([]*contracts.RLNMemberRegistered) // TODO: should these be sortered by index? we assume all members arrive in order
err := gm.rln.InsertMember(pubkey) for _, evt := range events {
if err != nil { pubkey := rln.Bytes32(evt.Pubkey.Bytes())
gm.log.Error("inserting member into merkletree", zap.Error(err)) // TODO: should we track indexes to identify missing?
return err err := gm.rln.InsertMember(pubkey)
} if err != nil {
gm.log.Error("inserting member into merkletree", zap.Error(err))
return err
}
}
err = gm.rootTracker.Sync() _, err := gm.rootTracker.UpdateLatestRoot(pair.Key.(uint64))
if err != nil { if err != nil {
return err return err
}
}
return nil
}
func (gm *DynamicGroupManager) RemoveMembers(toRemove *om.OrderedMap) error {
for pair := toRemove.Newest(); pair != nil; pair = pair.Prev() {
memberIndexes := pair.Value.([]uint64)
for _, index := range memberIndexes {
err := gm.rln.DeleteMember(uint(index))
if err != nil {
gm.log.Error("deleting member", zap.Error(err))
return err
}
}
gm.rootTracker.Backfill(pair.Key.(uint64))
} }
return nil return nil

View File

@ -0,0 +1,115 @@
package dynamic
import (
"context"
"math/big"
"sync"
"testing"
"github.com/ethereum/go-ethereum/core/types"
"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/utils"
"github.com/waku-org/go-zerokit-rln/rln"
)
func eventBuilder(blockNumber uint64, removed bool, pubkey int64, index int64) *contracts.RLNMemberRegistered {
return &contracts.RLNMemberRegistered{
Raw: types.Log{
BlockNumber: blockNumber,
Removed: removed,
},
Index: big.NewInt(index),
Pubkey: big.NewInt(pubkey),
}
}
func TestHandler(t *testing.T) {
// Create a RLN instance
rlnInstance, err := rln.NewRLN()
require.NoError(t, err)
rootTracker, err := group_manager.NewMerkleRootTracker(5, rlnInstance)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
_ = ctx
gm := &DynamicGroupManager{
rln: rlnInstance,
log: utils.Logger(),
cancel: cancel,
wg: sync.WaitGroup{},
rootTracker: rootTracker,
}
root0 := [32]byte{62, 31, 25, 34, 223, 182, 113, 211, 249, 18, 247, 234, 70, 30, 10, 136, 238, 132, 143, 221, 225, 43, 108, 24, 171, 26, 210, 197, 106, 231, 52, 33}
roots := gm.rootTracker.Roots()
require.Len(t, roots, 1)
require.Equal(t, roots[0], root0)
events := []*contracts.RLNMemberRegistered{eventBuilder(1, false, 0xaaaa, 1)}
err = handler(gm, events)
require.NoError(t, err)
roots = gm.rootTracker.Roots()
require.Len(t, roots, 2)
require.Equal(t, roots[0], root0)
require.Equal(t, roots[1], [32]byte{253, 232, 31, 10, 168, 25, 42, 0, 28, 221, 146, 119, 34, 212, 121, 51, 82, 55, 113, 181, 236, 3, 11, 190, 194, 144, 125, 59, 46, 171, 90, 43})
events = []*contracts.RLNMemberRegistered{
eventBuilder(1, false, 0xbbbb, 2),
eventBuilder(2, false, 0xcccc, 3),
eventBuilder(3, false, 0xdddd, 4),
eventBuilder(4, false, 0xeeee, 5),
}
err = handler(gm, events)
require.NoError(t, err)
// Root[1] should become [0]
roots = gm.rootTracker.Roots()
require.Len(t, roots, 5)
require.Equal(t, roots[0], [32]byte{253, 232, 31, 10, 168, 25, 42, 0, 28, 221, 146, 119, 34, 212, 121, 51, 82, 55, 113, 181, 236, 3, 11, 190, 194, 144, 125, 59, 46, 171, 90, 43})
require.Len(t, rootTracker.Buffer(), 1)
require.Equal(t, rootTracker.Buffer()[0], [32]byte{62, 31, 25, 34, 223, 182, 113, 211, 249, 18, 247, 234, 70, 30, 10, 136, 238, 132, 143, 221, 225, 43, 108, 24, 171, 26, 210, 197, 106, 231, 52, 33})
// We detect a fork
//
// [0] -> [1] -> [2] -> [3] -> [4] Our chain
// \
// \--> Real chain
// We should restore the valid roots from the buffer at the state the moment the chain forked
// In this case, just adding the original merkle root from empty tree
validRootsBeforeFork := roots[0:3]
events = []*contracts.RLNMemberRegistered{eventBuilder(3, true, 0xdddd, 4)}
err = handler(gm, events)
require.NoError(t, err)
roots = gm.rootTracker.Roots()
require.Len(t, roots, 4)
require.Equal(t, roots[0], root0)
require.Equal(t, roots[1], validRootsBeforeFork[0])
require.Equal(t, roots[2], validRootsBeforeFork[1])
require.Equal(t, roots[3], validRootsBeforeFork[2])
require.Len(t, rootTracker.Buffer(), 0)
// Adding multiple events for same block
events = []*contracts.RLNMemberRegistered{
eventBuilder(3, false, 0xdddd, 4),
eventBuilder(3, false, 0xeeee, 5),
}
err = handler(gm, events)
require.NoError(t, err)
roots = gm.rootTracker.Roots()
require.Len(t, roots, 5)
}

View File

@ -94,22 +94,7 @@ func (gm *DynamicGroupManager) Register(ctx context.Context) (*r.MembershipIndex
} }
// the types of inputs to this handler matches the MemberRegistered event/proc defined in the MembershipContract interface // the types of inputs to this handler matches the MemberRegistered event/proc defined in the MembershipContract interface
type RegistrationEventHandler = func(pubkey r.IDCommitment, index r.MembershipIndex) error type RegistrationEventHandler = func(*DynamicGroupManager, []*contracts.RLNMemberRegistered) error
func (gm *DynamicGroupManager) processLogs(evt *contracts.RLNMemberRegistered, handler RegistrationEventHandler) error {
if evt == nil {
return nil
}
var pubkey r.IDCommitment = r.Bytes32(evt.Pubkey.Bytes())
index := evt.Index.Int64()
if index <= gm.lastIndexLoaded {
return nil
}
gm.lastIndexLoaded = index
return handler(pubkey, r.MembershipIndex(uint(evt.Index.Int64())))
}
// HandleGroupUpdates mounts the supplied handler for the registration events emitting from the membership contract // HandleGroupUpdates mounts the supplied handler for the registration events emitting from the membership contract
// It connects to the eth client, subscribes to the `MemberRegistered` event emitted from the `MembershipContract` // It connects to the eth client, subscribes to the `MemberRegistered` event emitted from the `MembershipContract`
@ -128,36 +113,21 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
} }
func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *contracts.RLN, handler RegistrationEventHandler) error { func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *contracts.RLN, handler RegistrationEventHandler) error {
logIterator, err := rlnContract.FilterMemberRegistered(&bind.FilterOpts{Start: 0, End: nil, Context: ctx}) events, err := gm.getEvents(ctx, 0, nil)
if err != nil { if err != nil {
return err return err
} }
for { return handler(gm, events)
if !logIterator.Next() {
break
}
if logIterator.Error() != nil {
return logIterator.Error()
}
err = gm.processLogs(logIterator.Event, handler)
if err != nil {
return err
}
}
return nil
} }
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, rlnContract *contracts.RLN, handler RegistrationEventHandler, log *zap.Logger, errCh chan<- error) {
defer gm.wg.Done() defer gm.wg.Done()
// Watch for new events // Watch for new events
logSink := make(chan *contracts.RLNMemberRegistered)
firstErr := true firstErr := true
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) {
subs, err := rlnContract.WatchMemberRegistered(&bind.WatchOpts{Context: ctx, Start: nil}, logSink) s, err := gm.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")
@ -169,16 +139,23 @@ func (gm *DynamicGroupManager) watchNewEvents(ctx context.Context, rlnContract *
} }
firstErr = false firstErr = false
close(errCh) close(errCh)
return subs, err return s, err
}) })
defer subs.Unsubscribe() defer subs.Unsubscribe()
defer close(logSink) defer close(headerCh)
for { for {
select { select {
case evt := <-logSink: case h := <-headerCh:
err := gm.processLogs(evt, handler) blk := h.Number.Uint64()
events, err := gm.getEvents(ctx, blk, &blk)
if err != nil {
gm.log.Error("obtaining rln events", zap.Error(err))
}
err = handler(gm, events)
if err != nil { if err != nil {
gm.log.Error("processing rln log", zap.Error(err)) gm.log.Error("processing rln log", zap.Error(err))
} }
@ -192,3 +169,26 @@ func (gm *DynamicGroupManager) watchNewEvents(ctx context.Context, rlnContract *
} }
} }
} }
func (gm *DynamicGroupManager) getEvents(ctx context.Context, from uint64, to *uint64) ([]*contracts.RLNMemberRegistered, error) {
logIterator, err := gm.rlnContract.FilterMemberRegistered(&bind.FilterOpts{Start: from, End: to, Context: ctx})
if err != nil {
return nil, err
}
var results []*contracts.RLNMemberRegistered
for {
if !logIterator.Next() {
break
}
if logIterator.Error() != nil {
return nil, logIterator.Error()
}
results = append(results, logIterator.Event)
}
return results, nil
}

View File

@ -1,34 +1,133 @@
package group_manager package group_manager
import "github.com/waku-org/go-zerokit-rln/rln" import (
"sync"
type MerkleRootTracker struct { "github.com/waku-org/go-zerokit-rln/rln"
rln *rln.RLN )
acceptableRootWindowSize int
validMerkleRoots []rln.MerkleNode type RootsPerBlock struct {
root rln.MerkleNode
blockNumber uint64
} }
func NewMerkleRootTracker(acceptableRootWindowSize int, rlnInstance *rln.RLN) *MerkleRootTracker { type MerkleRootTracker struct {
return &MerkleRootTracker{ sync.RWMutex
rln *rln.RLN
acceptableRootWindowSize int
validMerkleRoots []RootsPerBlock
merkleRootBuffer []RootsPerBlock
}
const maxBufferSize = 20
func NewMerkleRootTracker(acceptableRootWindowSize int, rlnInstance *rln.RLN) (*MerkleRootTracker, error) {
result := &MerkleRootTracker{
acceptableRootWindowSize: acceptableRootWindowSize, acceptableRootWindowSize: acceptableRootWindowSize,
rln: rlnInstance, rln: rlnInstance,
} }
}
func (m *MerkleRootTracker) Sync() error { _, err := result.UpdateLatestRoot(0)
root, err := m.rln.GetMerkleRoot()
if err != nil { if err != nil {
return err return nil, err
} }
m.validMerkleRoots = append(m.validMerkleRoots, root) return result, nil
}
func (m *MerkleRootTracker) Backfill(fromBlockNumber uint64) {
m.Lock()
defer m.Unlock()
numBlocks := 0
for i := len(m.validMerkleRoots) - 1; i >= 0; i-- {
if m.validMerkleRoots[i].blockNumber >= fromBlockNumber {
numBlocks++
}
}
if numBlocks == 0 {
return
}
// Remove last roots
rootsToPop := numBlocks
if len(m.validMerkleRoots) < rootsToPop {
rootsToPop = len(m.validMerkleRoots)
}
m.validMerkleRoots = m.validMerkleRoots[0 : len(m.validMerkleRoots)-rootsToPop]
if len(m.merkleRootBuffer) == 0 {
return
}
// Backfill the tree's acceptable roots
rootsToRestore := numBlocks
bufferLen := len(m.merkleRootBuffer)
if bufferLen < rootsToRestore {
rootsToRestore = bufferLen
}
for i := 0; i < rootsToRestore; i++ {
x, newRootBuffer := m.merkleRootBuffer[len(m.merkleRootBuffer)-1], m.merkleRootBuffer[:len(m.merkleRootBuffer)-1] // Pop
m.validMerkleRoots = append([]RootsPerBlock{x}, m.validMerkleRoots...)
m.merkleRootBuffer = newRootBuffer
}
}
func (m *MerkleRootTracker) UpdateLatestRoot(blockNumber uint64) (rln.MerkleNode, error) {
m.Lock()
defer m.Unlock()
root, err := m.rln.GetMerkleRoot()
if err != nil {
return [32]byte{}, err
}
m.pushRoot(blockNumber, root)
return root, nil
}
func (m *MerkleRootTracker) pushRoot(blockNumber uint64, root [32]byte) {
m.validMerkleRoots = append(m.validMerkleRoots, RootsPerBlock{
root: root,
blockNumber: blockNumber,
})
// Maintain valid merkle root window
if len(m.validMerkleRoots) > m.acceptableRootWindowSize { if len(m.validMerkleRoots) > m.acceptableRootWindowSize {
m.merkleRootBuffer = append(m.merkleRootBuffer, m.validMerkleRoots[0])
m.validMerkleRoots = m.validMerkleRoots[1:] m.validMerkleRoots = m.validMerkleRoots[1:]
} }
return nil // Maintain merkle root buffer
if len(m.merkleRootBuffer) > maxBufferSize {
m.merkleRootBuffer = m.merkleRootBuffer[1:]
}
} }
func (m *MerkleRootTracker) Roots() []rln.MerkleNode { func (m *MerkleRootTracker) Roots() []rln.MerkleNode {
return m.validMerkleRoots m.RLock()
defer m.RUnlock()
result := make([]rln.MerkleNode, len(m.validMerkleRoots))
for i := range m.validMerkleRoots {
result[i] = m.validMerkleRoots[i].root
}
return result
}
func (m *MerkleRootTracker) Buffer() []rln.MerkleNode {
m.RLock()
defer m.RUnlock()
result := make([]rln.MerkleNode, len(m.merkleRootBuffer))
for i := range m.merkleRootBuffer {
result[i] = m.merkleRootBuffer[i].root
}
return result
} }

View File

@ -45,18 +45,9 @@ func (gm *StaticGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN, r
gm.rln = rlnInstance gm.rln = rlnInstance
gm.rootTracker = rootTracker gm.rootTracker = rootTracker
err := rootTracker.Sync()
if err != nil {
return err
}
// add members to the Merkle tree // add members to the Merkle tree
for _, member := range gm.group { for i, member := range gm.group {
if err := rlnInstance.InsertMember(member); err != nil { err := gm.insertMember(member, uint64(i+1))
return err
}
err = rootTracker.Sync()
if err != nil { if err != nil {
return err return err
} }
@ -67,8 +58,9 @@ func (gm *StaticGroupManager) Start(ctx context.Context, rlnInstance *rln.RLN, r
return nil return nil
} }
func (gm *StaticGroupManager) InsertMember(pubkey rln.IDCommitment) error { func (gm *StaticGroupManager) insertMember(pubkey rln.IDCommitment, index uint64) error {
gm.log.Debug("a new key is added", zap.Binary("pubkey", pubkey[:])) gm.log.Debug("a new key is added", zap.Binary("pubkey", pubkey[:]), zap.Uint64("index", index))
// assuming all the members arrive in order // assuming all the members arrive in order
err := gm.rln.InsertMember(pubkey) err := gm.rln.InsertMember(pubkey)
if err != nil { if err != nil {
@ -76,7 +68,7 @@ func (gm *StaticGroupManager) InsertMember(pubkey rln.IDCommitment) error {
return err return err
} }
err = gm.rootTracker.Sync() _, err = gm.rootTracker.UpdateLatestRoot(index)
if err != nil { if err != nil {
return err return err
} }

View File

@ -78,9 +78,12 @@ func (s *WakuRLNRelaySuite) TestUpdateLogAndHasDuplicate() {
rlnInstance, err := r.NewRLN() rlnInstance, err := r.NewRLN()
s.Require().NoError(err) s.Require().NoError(err)
rootTracker, err := group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance)
s.Require().NoError(err)
rlnRelay := &WakuRLNRelay{ rlnRelay := &WakuRLNRelay{
nullifierLog: make(map[r.Nullifier][]r.ProofMetadata), nullifierLog: make(map[r.Nullifier][]r.ProofMetadata),
rootTracker: group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance), rootTracker: rootTracker,
} }
epoch := r.GetCurrentEpoch() epoch := r.GetCurrentEpoch()
@ -166,9 +169,12 @@ func (s *WakuRLNRelaySuite) TestValidateMessage() {
groupManager, err := static.NewStaticGroupManager(groupIDCommitments, idCredential, index, utils.Logger()) groupManager, err := static.NewStaticGroupManager(groupIDCommitments, idCredential, index, utils.Logger())
s.Require().NoError(err) s.Require().NoError(err)
rootTracker, err := group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance)
s.Require().NoError(err)
rlnRelay := &WakuRLNRelay{ rlnRelay := &WakuRLNRelay{
groupManager: groupManager, groupManager: groupManager,
rootTracker: group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance), rootTracker: rootTracker,
RLN: rlnInstance, RLN: rlnInstance,
nullifierLog: make(map[r.Nullifier][]r.ProofMetadata), nullifierLog: make(map[r.Nullifier][]r.ProofMetadata),
log: utils.Logger(), log: utils.Logger(),
@ -177,6 +183,9 @@ func (s *WakuRLNRelaySuite) TestValidateMessage() {
//get the current epoch time //get the current epoch time
now := time.Now() now := time.Now()
err = groupManager.Start(context.Background(), rlnInstance, rootTracker)
s.Require().NoError(err)
// create some messages from the same peer and append rln proof to them, except wm4 // create some messages from the same peer and append rln proof to them, except wm4
wm1 := &pb.WakuMessage{Payload: []byte("Valid message")} wm1 := &pb.WakuMessage{Payload: []byte("Valid message")}

View File

@ -62,11 +62,16 @@ func New(
return nil, err return nil, err
} }
rootTracker, err := group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance)
if err != nil {
return nil, err
}
// create the WakuRLNRelay // create the WakuRLNRelay
rlnPeer := &WakuRLNRelay{ rlnPeer := &WakuRLNRelay{
RLN: rlnInstance, RLN: rlnInstance,
groupManager: groupManager, groupManager: groupManager,
rootTracker: group_manager.NewMerkleRootTracker(AcceptableRootWindowSize, rlnInstance), rootTracker: rootTracker,
pubsubTopic: pubsubTopic, pubsubTopic: pubsubTopic,
contentTopic: contentTopic, contentTopic: contentTopic,
relay: relay, relay: relay,