Add GetMerkleProof (#17)
This commit is contained in:
parent
06e6fa3fd1
commit
7e086e8f89
6
go.mod
6
go.mod
|
@ -4,9 +4,9 @@ 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-arm v0.0.0-20230916171929-1dd9494ff065
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240116135015-f6f595c7b8ef
|
||||
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240116134931-a8b8c6ab4b80
|
||||
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240116135046-2875fec12afc
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
10
go.sum
10
go.sum
|
@ -15,10 +15,20 @@ 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-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-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-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-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-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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -82,6 +82,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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
70
rln/rln.go
70
rln/rln.go
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/waku-org/go-zerokit-rln/rln/link"
|
||||
)
|
||||
|
@ -393,6 +394,75 @@ 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
|
||||
}
|
||||
|
||||
// Check if we can read the first byte
|
||||
if len(proofBytes) < 8 {
|
||||
return MerkleProof{}, errors.New(fmt.Sprintf("wrong output size: %d", len(proofBytes)))
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// With numElements we can determine the expected length of the proof.
|
||||
expectedLen := 8 + int(32*numElements.Uint64()) + 8 + int(numElements.Uint64())
|
||||
if len(proofBytes) != expectedLen {
|
||||
return MerkleProof{}, errors.New(fmt.Sprintf("wrong output size expected: %d, current: %d",
|
||||
expectedLen,
|
||||
len(proofBytes)))
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
Loading…
Reference in New Issue