Add GetMerkleProof

This commit is contained in:
alrevuelta 2024-01-16 13:18:54 +01:00
parent 06e6fa3fd1
commit 43579987bb
No known key found for this signature in database
GPG Key ID: F345C9F3CCDB886E
8 changed files with 117 additions and 1 deletions

2
go.mod
View File

@ -4,7 +4,7 @@ go 1.19
require (
github.com/stretchr/testify v1.7.2
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20230916172309-ee0ee61dde2b
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116121347-ee5a1d931442
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1
)

4
go.sum
View File

@ -15,6 +15,10 @@ github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
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-apple v0.0.0-20240116092850-ad40ef83a1b5 h1:yqco0Gy1zdBDkHMAPqJ95jSlPVUxAsxK5xVeiUdxQN8=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116092850-ad40ef83a1b5/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116121347-ee5a1d931442 h1:xDs9CAyhgOq9PXo06zTnd8VsPjngAyTGujeDTfsTwGg=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116121347-ee5a1d931442/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=

View File

@ -83,6 +83,10 @@ func (i RLNWrapper) GetLeaf(index uint) ([]byte, error) {
return i.ffi.GetLeaf(index)
}
func (i RLNWrapper) GetMerkleProof(index uint) ([]byte, error) {
return i.ffi.GetMerkleProof(index)
}
func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
return i.ffi.GenerateRLNProof(input)
}

View File

@ -82,6 +82,10 @@ func (i RLNWrapper) GetLeaf(index uint) ([]byte, error) {
return i.ffi.GetLeaf(index)
}
func (i RLNWrapper) GetProof(index uint) ([]byte, error) {
return i.ffi.GetProof(index)
}
func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
return i.ffi.GenerateRLNProof(input)
}

View File

@ -83,6 +83,10 @@ func (i RLNWrapper) GetLeaf(index uint) ([]byte, error) {
return i.ffi.GetLeaf(index)
}
func (i RLNWrapper) GetProof(index uint) ([]byte, error) {
return i.ffi.GetProof(index)
}
func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
return i.ffi.GenerateRLNProof(input)
}

View File

@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math/big"
"github.com/waku-org/go-zerokit-rln/rln/link"
)
@ -393,6 +394,62 @@ func (r *RLN) GetLeaf(index MembershipIndex) (IDCommitment, error) {
return result, nil
}
// GetMerkleProof returns the Merkle proof for the element at the specified index
// The output should be parsed as: num_elements<8>|path_elements<var1>|num_indexes<8>|path_indexes<var2>
// where num_elements indicate var1 array size and num_indexes indicate var2 array size.
// Both num_elements and num_indexes shall be equal and match the tree depth.
// A tree with depth 20 has 676 bytes = 8 + 32 * 20 + 8 + 20 * 1
// Proof elements are stored as little endian
func (r *RLN) GetMerkleProof(index MembershipIndex) (MerkleProof, error) {
proofBytes, err := r.w.GetMerkleProof(index)
if err != nil {
return MerkleProof{}, err
}
var result MerkleProof
var numElements big.Int
var numIndexes big.Int
offset := 0
// Get amounf of elements in the proof
numElements.SetBytes(revert(proofBytes[offset : offset+8]))
offset += 8
result.PathElements = make([]MerkleNode, numElements.Uint64())
for i := uint64(0); i < numElements.Uint64(); i++ {
copy(result.PathElements[i][:], proofBytes[offset:offset+32])
offset += 32
}
// Get amount of indexes in the path
numIndexes.SetBytes(revert(proofBytes[offset : offset+8]))
offset += 8
// Both numElements and numIndexes shall be equal and match the tree depth.
if numIndexes.Uint64() != numElements.Uint64() {
return MerkleProof{}, errors.New(fmt.Sprintf("amount of values in path and indexes do not match: %s vs %s",
numElements.String(), numIndexes.String()))
}
// TODO: Depth check, but currently not accesible
result.PathIndexes = make([]uint8, numIndexes.Uint64())
for i := uint64(0); i < numIndexes.Uint64(); i++ {
result.PathIndexes[i] = proofBytes[offset]
offset += 1
}
if offset != len(proofBytes) {
return MerkleProof{}, errors.New(
fmt.Sprintf("error parsing proof read: %d, length; %d", offset, len(proofBytes)))
}
return result, nil
}
// AddAll adds members to the Merkle tree
func (r *RLN) AddAll(list []IDCommitment) error {
for _, member := range list {

View File

@ -312,6 +312,44 @@ func (s *RLNSuite) TestInvalidProof() {
s.False(verified)
}
func (s *RLNSuite) TestGetMerkleProof() {
for _, treeDepth := range []TreeDepth{TreeDepth15, TreeDepth19, TreeDepth20} {
treeDepthInt := int(treeDepth)
rln, err := NewWithConfig(treeDepth, nil)
s.NoError(err)
leaf0 := [32]byte{0x00}
leaf1 := [32]byte{0x01}
leaf5 := [32]byte{0x05}
rln.InsertMemberAt(0, leaf0)
rln.InsertMemberAt(1, leaf1)
rln.InsertMemberAt(5, leaf5)
b1, err := rln.GetMerkleProof(0)
s.NoError(err)
s.Equal(treeDepthInt, len(b1.PathElements))
s.Equal(treeDepthInt, len(b1.PathIndexes))
// First path is right leaf [0, 1]
s.EqualValues(leaf1, b1.PathElements[0])
b2, err := rln.GetMerkleProof(4)
s.NoError(err)
s.Equal(treeDepthInt, len(b2.PathElements))
s.Equal(treeDepthInt, len(b2.PathIndexes))
// First path is right leaf [4, 5]
s.EqualValues(leaf5, b2.PathElements[0])
b3, err := rln.GetMerkleProof(10)
s.NoError(err)
s.Equal(treeDepthInt, len(b3.PathElements))
s.Equal(treeDepthInt, len(b3.PathIndexes))
// First path is right leaf. But its empty
s.EqualValues([32]byte{0x00}, b3.PathElements[0])
}
}
func (s *RLNSuite) TestEpochConsistency() {
// check edge cases
var epoch uint64 = math.MaxUint64

View File

@ -63,6 +63,11 @@ type RateLimitProof struct {
RLNIdentifier RLNIdentifier `json:"rlnIdentifier"`
}
type MerkleProof struct {
PathElements []MerkleNode `json:"pathElements"`
PathIndexes []uint8 `json:"pathIndexes"`
}
type TreeDepth int
const (