mirror of
https://github.com/logos-messaging/logos-messaging-go.git
synced 2026-01-07 08:23:06 +00:00
Proof of Concept: Merkle proof provider service
This commit is contained in:
parent
190d8e8e08
commit
8d243366c3
@ -1,10 +1,15 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-zerokit-rln/rln"
|
||||
)
|
||||
|
||||
type DebugService struct {
|
||||
@ -20,8 +25,15 @@ type InfoReply struct {
|
||||
ListenAddresses []string `json:"listenAddresses,omitempty"`
|
||||
}
|
||||
|
||||
// Run as:
|
||||
// ./build/waku --rest --rest-address=0.0.0.0 --rln-relay=true --rln-relay-dynamic=true --rln-relay-eth-client-address=wss://sepolia.infura.io/ws/v3/4576482c0f474483ac709755f2663b20 --rln-relay-eth-contract-address=0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4
|
||||
|
||||
// Example usage (replace by your public commitment)
|
||||
// curl http://localhost:8645/debug/v1/merkleProof/15506699537643273163469326218249028331014943998871371946527772121417127479348
|
||||
|
||||
const routeDebugInfoV1 = "/debug/v1/info"
|
||||
const routeDebugVersionV1 = "/debug/v1/version"
|
||||
const routeDebugGetMerkleProofV1 = "/debug/v1/merkleProof/{commitment}"
|
||||
|
||||
func NewDebugService(node *node.WakuNode, m *chi.Mux) *DebugService {
|
||||
d := &DebugService{
|
||||
@ -31,6 +43,7 @@ func NewDebugService(node *node.WakuNode, m *chi.Mux) *DebugService {
|
||||
|
||||
m.Get(routeDebugInfoV1, d.getV1Info)
|
||||
m.Get(routeDebugVersionV1, d.getV1Version)
|
||||
m.Get(routeDebugGetMerkleProofV1, d.getV1MerkleProof)
|
||||
|
||||
return d
|
||||
}
|
||||
@ -50,3 +63,102 @@ func (d *DebugService) getV1Version(w http.ResponseWriter, req *http.Request) {
|
||||
response := VersionResponse(node.GetVersionInfo().String())
|
||||
writeErrOrResponse(w, nil, response)
|
||||
}
|
||||
|
||||
type MerkleProofResponse struct {
|
||||
MerkleRoot string `json:"root"`
|
||||
MerkePathElements []string `json:"pathElements"`
|
||||
MerkePathIndexes []uint `json:"pathIndexes"`
|
||||
LeafIndex uint64 `json:"leafIndex"`
|
||||
CommitmentId string `json:"commitmentId"`
|
||||
}
|
||||
|
||||
func (d *DebugService) getV1MerkleProof(w http.ResponseWriter, req *http.Request) {
|
||||
commitmentReq := chi.URLParam(req, "commitment")
|
||||
if commitmentReq == "" {
|
||||
writeErrResponse(w, nil, fmt.Errorf("commitment is empty"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
commitmentReqBig := new(big.Int)
|
||||
commitmentReqBig, ok := commitmentReqBig.SetString(commitmentReq, 10)
|
||||
if !ok {
|
||||
writeErrResponse(w, nil, fmt.Errorf("commitment is not a number"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("commitmentReq: ", commitmentReq)
|
||||
|
||||
// Some dirty way to access rln and group manager
|
||||
rlnInstance := d.node.RLNInstance
|
||||
groupManager := d.node.GroupManager
|
||||
|
||||
ready, err := groupManager.IsReady(context.Background())
|
||||
if err != nil {
|
||||
writeErrResponse(w, nil, fmt.Errorf("could not check if service was ready"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !ready {
|
||||
writeErrResponse(w, nil, fmt.Errorf("service is not ready"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
found := false
|
||||
membershipIndex := uint(0)
|
||||
for leafIdx := uint(0); leafIdx < rlnInstance.LeavesSet(); leafIdx++ {
|
||||
|
||||
leaf, err := rlnInstance.GetLeaf(leafIdx)
|
||||
if err != nil {
|
||||
writeErrResponse(w, nil, fmt.Errorf("could not get leaf"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
leafBig := rln.Bytes32ToBigInt(leaf)
|
||||
|
||||
if leafBig.Cmp(commitmentReqBig) == 0 {
|
||||
found = true
|
||||
membershipIndex = leafIdx
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
writeErrResponse(w, nil, fmt.Errorf("commitment not found: %s", commitmentReqBig.String()), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("membershipIndex: ", membershipIndex)
|
||||
|
||||
merkleProof, err := rlnInstance.GetMerkleProof(rln.MembershipIndex(membershipIndex))
|
||||
if err != nil {
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
elementsStr := make([]string, 0)
|
||||
indexesStr := make([]uint, 0)
|
||||
|
||||
for _, path := range merkleProof.PathElements {
|
||||
fmt.Println("path: ", path)
|
||||
elementsStr = append(elementsStr, "0x"+hex.EncodeToString(path[:]))
|
||||
}
|
||||
for _, index := range merkleProof.PathIndexes {
|
||||
indexesStr = append(indexesStr, uint(index))
|
||||
}
|
||||
|
||||
// TODO: Not nide to get proof and root in different non atomic calls. In an unlikely edge case the tree can change between the two calls
|
||||
// if a membership is added. Proof of concept by now.
|
||||
merkleRoot, err := rlnInstance.GetMerkleRoot()
|
||||
if err != nil {
|
||||
writeErrOrResponse(w, err, nil)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("merkleRoot: ", merkleRoot)
|
||||
|
||||
writeErrOrResponse(w, nil, MerkleProofResponse{
|
||||
MerkleRoot: "0x" + hex.EncodeToString(merkleRoot[:]),
|
||||
MerkePathElements: elementsStr,
|
||||
MerkePathIndexes: indexesStr,
|
||||
LeafIndex: uint64(membershipIndex),
|
||||
CommitmentId: commitmentReqBig.String(),
|
||||
})
|
||||
}
|
||||
|
||||
8
go.mod
8
go.mod
@ -41,7 +41,7 @@ require (
|
||||
github.com/libp2p/go-libp2p-mplex v0.9.0
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0
|
||||
github.com/waku-org/go-noise v0.0.4
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240116153345-7e086e8f8930
|
||||
github.com/wk8/go-ordered-map v1.0.0
|
||||
)
|
||||
|
||||
@ -73,9 +73,9 @@ require (
|
||||
github.com/rjeczalik/notify v0.9.3 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/status-im/status-go/extkeys v1.1.2 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b // indirect
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116135015-f6f595c7b8ef // indirect
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240116134931-a8b8c6ab4b80 // indirect
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240116135046-2875fec12afc // indirect
|
||||
go.uber.org/dig v1.17.1 // indirect
|
||||
go.uber.org/fx v1.20.1 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@ -1540,14 +1540,14 @@ github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0 h1:R
|
||||
github.com/waku-org/go-libp2p-rendezvous v0.0.0-20240110193335-a67d1cc760a0/go.mod h1:EhZP9fee0DYjKH/IOQvoNSy1tSHp2iZadsHGphcAJgY=
|
||||
github.com/waku-org/go-noise v0.0.4 h1:ZfQDcCw8pazm89EBl5SXY7GGAnzDQb9AHFXlw3Ktbvk=
|
||||
github.com/waku-org/go-noise v0.0.4/go.mod h1:+PWRfs2eSOVwKrPcQlfhwDngSh3faL/1QoxvoqggEKc=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59 h1:jisj+OCI6QydLtFq3Pyhu49wl9ytPN7oAHjMfepHDrA=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240102145250-fa738c0bdf59/go.mod h1:1PdBdPzyTaKt3VnpAHk3zj+r9dXPFOr3IHZP9nFle6E=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b h1:KgZVhsLkxsj5gb/FfndSCQu6VYwALrCOgYI3poR95yE=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 h1:Sd7QD/1Yo2o2M1MY49F8Zr4KNBPUEK5cz5HoXQVJbrs=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 h1:4HSdWMFMufpRo3ECTX6BrvA+VzKhXZf7mS0rTa5cCWU=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240116153345-7e086e8f8930 h1:R9s+zA28gCX3e6b3iZKwLX7oRh3G15r1eSuOglSwUfk=
|
||||
github.com/waku-org/go-zerokit-rln v0.1.14-0.20240116153345-7e086e8f8930/go.mod h1:IOXLch4yJlN8WMf3S8kbGiZPMV1xYQ+xQ3D1yOGUAxg=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116135015-f6f595c7b8ef h1:MAkZryAeRhiH3TKHRK2h+WztZI1VqfQ/oeXMIxKZNy0=
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116135015-f6f595c7b8ef/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240116134931-a8b8c6ab4b80 h1:3KObRaYJnTI41U0reNBk7DYr5PVCTq8T9gJLXGfPfaY=
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240116134931-a8b8c6ab4b80/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240116135046-2875fec12afc h1:YjIgIrqlNVC+hXNy2ykYy3JvBKima64J9jXbKM/ULpw=
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240116135046-2875fec12afc/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
|
||||
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/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
|
||||
@ -42,10 +42,12 @@ import (
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/peer_exchange"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/rln/group_manager/dynamic"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/store"
|
||||
"github.com/waku-org/go-waku/waku/v2/rendezvous"
|
||||
"github.com/waku-org/go-waku/waku/v2/service"
|
||||
"github.com/waku-org/go-waku/waku/v2/timesource"
|
||||
r "github.com/waku-org/go-zerokit-rln/rln"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
)
|
||||
@ -84,11 +86,14 @@ type RLNRelay interface {
|
||||
}
|
||||
|
||||
type WakuNode struct {
|
||||
host host.Host
|
||||
opts *WakuNodeParameters
|
||||
log *zap.Logger
|
||||
timesource timesource.Timesource
|
||||
metrics Metrics
|
||||
// TODO: quick and dirty way to expose
|
||||
RLNInstance *r.RLN
|
||||
GroupManager *dynamic.DynamicGroupManager
|
||||
host host.Host
|
||||
opts *WakuNodeParameters
|
||||
log *zap.Logger
|
||||
timesource timesource.Timesource
|
||||
metrics Metrics
|
||||
|
||||
peerstore peerstore.Peerstore
|
||||
peerConnector *peermanager.PeerConnectionStrategy
|
||||
@ -286,10 +291,12 @@ func New(opts ...WakuNodeOption) (*WakuNode, error) {
|
||||
relay.WithMaxMsgSize(w.opts.maxMsgSizeBytes))
|
||||
|
||||
if w.opts.enableRelay {
|
||||
err = w.setupRLNRelay()
|
||||
err, rlnInstance, groupManager := w.setupRLNRelay()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.RLNInstance = rlnInstance
|
||||
w.GroupManager = groupManager
|
||||
}
|
||||
|
||||
w.opts.legacyFilterOpts = append(w.opts.legacyFilterOpts, legacy_filter.WithPeerManager(w.peermanager))
|
||||
|
||||
@ -21,22 +21,22 @@ func (w *WakuNode) RLNRelay() RLNRelay {
|
||||
return w.rlnRelay
|
||||
}
|
||||
|
||||
func (w *WakuNode) setupRLNRelay() error {
|
||||
func (w *WakuNode) setupRLNRelay() (error, *r.RLN, *dynamic.DynamicGroupManager) {
|
||||
var err error
|
||||
|
||||
if !w.opts.enableRLN {
|
||||
return nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
if !w.opts.enableRelay {
|
||||
return errors.New("rln requires relay")
|
||||
return errors.New("rln requires relay"), nil, nil
|
||||
}
|
||||
|
||||
var groupManager group_manager.GroupManager
|
||||
|
||||
rlnInstance, rootTracker, err := rln.GetRLNInstanceAndRootTracker(w.opts.rlnTreePath)
|
||||
if err != nil {
|
||||
return err
|
||||
return err, nil, nil
|
||||
}
|
||||
if !w.opts.rlnRelayDynamic {
|
||||
w.log.Info("setting up waku-rln-relay in off-chain mode")
|
||||
@ -49,12 +49,12 @@ func (w *WakuNode) setupRLNRelay() error {
|
||||
// set up rln relay inputs
|
||||
groupKeys, idCredential, err := static.Setup(index)
|
||||
if err != nil {
|
||||
return err
|
||||
return err, nil, nil
|
||||
}
|
||||
|
||||
groupManager, err = static.NewStaticGroupManager(groupKeys, idCredential, index, rlnInstance, rootTracker, w.log)
|
||||
if err != nil {
|
||||
return err
|
||||
return err, nil, nil
|
||||
}
|
||||
} else {
|
||||
w.log.Info("setting up waku-rln-relay in on-chain mode")
|
||||
@ -63,7 +63,7 @@ func (w *WakuNode) setupRLNRelay() error {
|
||||
if w.opts.keystorePath != "" {
|
||||
appKeystore, err = keystore.New(w.opts.keystorePath, dynamic.RLNAppInfo, w.log)
|
||||
if err != nil {
|
||||
return err
|
||||
return err, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ func (w *WakuNode) setupRLNRelay() error {
|
||||
w.log,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return err, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ func (w *WakuNode) setupRLNRelay() error {
|
||||
|
||||
w.Relay().RegisterDefaultValidator(w.rlnRelay.Validator(w.opts.rlnSpamHandler))
|
||||
|
||||
return nil
|
||||
return nil, rlnInstance, groupManager.(*dynamic.DynamicGroupManager)
|
||||
}
|
||||
|
||||
func (w *WakuNode) startRlnRelay(ctx context.Context) error {
|
||||
|
||||
@ -52,10 +52,10 @@ func (gm *DynamicGroupManager) handler(events []*contracts.RLNMemberRegistered,
|
||||
|
||||
toRemoveTable := om.New()
|
||||
toInsertTable := om.New()
|
||||
if gm.lastBlockProcessed == 0 {
|
||||
gm.lastBlockProcessed = latestProcessBlock
|
||||
}
|
||||
lastBlockProcessed := gm.lastBlockProcessed
|
||||
//if gm.lastBlockProcessed == 0 {
|
||||
// gm.lastBlockProcessed = latestProcessBlock
|
||||
//}
|
||||
//lastBlockProcessed := gm.lastBlockProcessed
|
||||
for _, event := range events {
|
||||
if event.Raw.Removed {
|
||||
var indexes []uint
|
||||
@ -74,9 +74,9 @@ func (gm *DynamicGroupManager) handler(events []*contracts.RLNMemberRegistered,
|
||||
eventsPerBlock = append(eventsPerBlock, event)
|
||||
toInsertTable.Set(event.Raw.BlockNumber, eventsPerBlock)
|
||||
|
||||
if event.Raw.BlockNumber > lastBlockProcessed {
|
||||
lastBlockProcessed = event.Raw.BlockNumber
|
||||
}
|
||||
//if event.Raw.BlockNumber > lastBlockProcessed {
|
||||
// lastBlockProcessed = event.Raw.BlockNumber
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,9 @@ func (gm *DynamicGroupManager) handler(events []*contracts.RLNMemberRegistered,
|
||||
return err
|
||||
}
|
||||
|
||||
gm.lastBlockProcessed = lastBlockProcessed
|
||||
// TODO: Commented code above is a bug I think. lastBlockProcessed was not being
|
||||
// updated properly.
|
||||
gm.lastBlockProcessed = latestProcessBlock
|
||||
err = gm.SetMetadata(RLNMetadata{
|
||||
LastProcessedBlock: gm.lastBlockProcessed,
|
||||
ChainID: gm.web3Config.ChainID,
|
||||
@ -310,6 +312,8 @@ func (gm *DynamicGroupManager) IsReady(ctx context.Context) (bool, error) {
|
||||
return false, fmt.Errorf("could not retrieve latest block: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("latestBlockNumber: ", latestBlockNumber, " gm.lastBlockProcessed: ", gm.lastBlockProcessed)
|
||||
|
||||
gm.lastBlockProcessedMutex.RLock()
|
||||
allBlocksProcessed := gm.lastBlockProcessed >= latestBlockNumber
|
||||
gm.lastBlockProcessedMutex.RUnlock()
|
||||
@ -325,3 +329,7 @@ func (gm *DynamicGroupManager) IsReady(ctx context.Context) (bool, error) {
|
||||
|
||||
return syncProgress == nil, nil // syncProgress only has a value while node is syncing
|
||||
}
|
||||
|
||||
func GetRLN(gm *DynamicGroupManager) *rln.RLN {
|
||||
return gm.rln
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user