mirror of https://github.com/status-im/go-waku.git
fix(rln-relay): RLN DB should be aware of chain and contract address
This commit is contained in:
parent
7e36f91a5a
commit
5422af8130
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"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"
|
||||
|
@ -97,12 +98,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,
|
||||
})
|
||||
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))
|
||||
gm.log.Debug("rln metadata persisted", zap.Uint64("lastProcessedBlock", gm.lastBlockProcessed), zap.Uint64("chainID", gm.chainId.Uint64()), logging.HexBytes("contractAddress", gm.membershipContractAddress[:]))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -43,6 +43,7 @@ func TestHandler(t *testing.T) {
|
|||
log: utils.Logger(),
|
||||
cancel: cancel,
|
||||
wg: sync.WaitGroup{},
|
||||
chainId: big.NewInt(1),
|
||||
rootTracker: rootTracker,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,27 +3,47 @@ package dynamic
|
|||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// RLNMetadata persists attributes in the RLN database
|
||||
type RLNMetadata struct {
|
||||
LastProcessedBlock uint64
|
||||
ChainID *big.Int
|
||||
ContractAddress common.Address
|
||||
}
|
||||
|
||||
// Serialize converts a RLNMetadata into a binary format expected by zerokit's RLN
|
||||
func (r RLNMetadata) Serialize() []byte {
|
||||
result := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(result, r.LastProcessedBlock)
|
||||
chainID := r.ChainID
|
||||
if chainID == nil {
|
||||
chainID = big.NewInt(0)
|
||||
}
|
||||
|
||||
var result []byte
|
||||
result = binary.LittleEndian.AppendUint64(result, r.LastProcessedBlock)
|
||||
result = binary.LittleEndian.AppendUint64(result, chainID.Uint64())
|
||||
result = append(result, r.ContractAddress.Bytes()...)
|
||||
return result
|
||||
}
|
||||
|
||||
const lastProcessedBlockOffset = 0
|
||||
const chainIDOffset = lastProcessedBlockOffset + 8
|
||||
const contractAddressOffset = chainIDOffset + 8
|
||||
const metadataByteLen = 8 + 8 + 20 // 2 uint64 fields and a 20bytes address
|
||||
|
||||
// DeserializeMetadata converts a byte slice into a RLNMetadata instance
|
||||
func DeserializeMetadata(b []byte) (RLNMetadata, error) {
|
||||
if len(b) != 8 {
|
||||
if len(b) != metadataByteLen {
|
||||
return RLNMetadata{}, errors.New("wrong size")
|
||||
}
|
||||
|
||||
return RLNMetadata{
|
||||
LastProcessedBlock: binary.LittleEndian.Uint64(b),
|
||||
LastProcessedBlock: binary.LittleEndian.Uint64(b[lastProcessedBlockOffset:chainIDOffset]),
|
||||
ChainID: new(big.Int).SetUint64(binary.LittleEndian.Uint64(b[chainIDOffset:contractAddressOffset])),
|
||||
ContractAddress: common.BytesToAddress(b[contractAddressOffset:]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMetadata(t *testing.T) {
|
||||
|
||||
metadata := &RLNMetadata{
|
||||
LastProcessedBlock: 128,
|
||||
ChainID: big.NewInt(1155511),
|
||||
ContractAddress: common.HexToAddress("0x9c09146844c1326c2dbc41c451766c7138f88155"),
|
||||
}
|
||||
|
||||
serializedMetadata := metadata.Serialize()
|
||||
|
||||
unserializedMetadata, err := DeserializeMetadata(serializedMetadata)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, metadata.ChainID.Uint64(), unserializedMetadata.ChainID.Uint64())
|
||||
require.Equal(t, metadata.LastProcessedBlock, unserializedMetadata.LastProcessedBlock)
|
||||
require.Equal(t, metadata.ContractAddress.Hex(), unserializedMetadata.ContractAddress.Hex())
|
||||
|
||||
// Handle cases where the chainId is not specified (for some reason?)
|
||||
metadata.ChainID = nil
|
||||
serializedMetadata = metadata.Serialize()
|
||||
unserializedMetadata, err = DeserializeMetadata(serializedMetadata)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), unserializedMetadata.ChainID.Uint64())
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
@ -20,7 +21,24 @@ type RegistrationEventHandler = func(*DynamicGroupManager, []*contracts.RLNMembe
|
|||
// It connects to the eth client, subscribes to the `MemberRegistered` event emitted from the `MembershipContract`
|
||||
// and collects all the events, for every received event, it calls the `handler`
|
||||
func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler RegistrationEventHandler) error {
|
||||
err := gm.loadOldEvents(ctx, gm.rlnContract, handler)
|
||||
fromBlock := uint64(0)
|
||||
metadata, err := gm.GetMetadata()
|
||||
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() {
|
||||
return errors.New("persisted data: chain id mismatch")
|
||||
}
|
||||
|
||||
if !bytes.Equal(gm.membershipContractAddress[:], metadata.ContractAddress[:]) {
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -32,16 +50,7 @@ func (gm *DynamicGroupManager) HandleGroupUpdates(ctx context.Context, handler R
|
|||
return <-errCh
|
||||
}
|
||||
|
||||
func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *contracts.RLN, handler RegistrationEventHandler) error {
|
||||
fromBlock := uint64(0)
|
||||
metadata, err := gm.GetMetadata()
|
||||
if err == nil {
|
||||
fromBlock = metadata.LastProcessedBlock
|
||||
gm.log.Info("resuming onchain sync", zap.Uint64("fromBlock", fromBlock))
|
||||
} else {
|
||||
gm.log.Warn("could not load last processed block from metadata. Starting onchain sync from scratch", zap.Error(err))
|
||||
}
|
||||
|
||||
func (gm *DynamicGroupManager) loadOldEvents(ctx context.Context, rlnContract *contracts.RLN, fromBlock uint64, handler RegistrationEventHandler) error {
|
||||
events, err := gm.getEvents(ctx, fromBlock, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in New Issue