Custom witness proof with RLN v2 (#22)

This commit is contained in:
Alvaro Revuelta 2024-05-30 14:53:54 +02:00 committed by GitHub
parent 54bb48f178
commit 84d12e61d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 149 additions and 104 deletions

6
go.mod
View File

@ -6,9 +6,9 @@ require (
github.com/consensys/gnark-crypto v0.12.1 github.com/consensys/gnark-crypto v0.12.1
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240523161310-d005fe7ba59c github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240529153423-5df5db48b69f
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240523161300-8203361a01d0 github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240529153432-be2c8ac0a840
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240523161247-6f16d12c5a86 github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240529153442-f5fb416605f5
golang.org/x/crypto v0.18.0 golang.org/x/crypto v0.18.0
) )

8
go.sum
View File

@ -25,14 +25,22 @@ github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240522110429-626138029176 h1:e
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240522110429-626138029176/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48= github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240522110429-626138029176/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240523161310-d005fe7ba59c h1:/eGH8EAt5/zGfNRBQ0nJMrfZDeXRSJrm8E8uCPlsC3A= github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240523161310-d005fe7ba59c h1:/eGH8EAt5/zGfNRBQ0nJMrfZDeXRSJrm8E8uCPlsC3A=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240523161310-d005fe7ba59c/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48= github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240523161310-d005fe7ba59c/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240528140707-ed6b40a98d7b h1:LEa2s1p+Z8SN475dVr3XDmvmGyKzIDKPcAQ+6hTyVwA=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240528140707-ed6b40a98d7b/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240529153423-5df5db48b69f h1:CEBW4vu8I60OakKExZUE7G4oY7Z/glQXxPYedpZ4Sq8=
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240529153423-5df5db48b69f/go.mod h1:KYykqtdApHVYZ3G0spwMnoxc5jH5eI3jyO9SwsSfi48=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240124081101-5e4387508113 h1:dPwc4LAWLXb4Pssej/NtGA9A0UMQwi+JafQPdnhjRWM= github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240124081101-5e4387508113 h1:dPwc4LAWLXb4Pssej/NtGA9A0UMQwi+JafQPdnhjRWM=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240124081101-5e4387508113/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4= github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240124081101-5e4387508113/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240523161300-8203361a01d0 h1:IvtkZOcApOkEmHkT/drDmMtY6fdYpF7x4sesWyIURpI= github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240523161300-8203361a01d0 h1:IvtkZOcApOkEmHkT/drDmMtY6fdYpF7x4sesWyIURpI=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240523161300-8203361a01d0/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4= github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240523161300-8203361a01d0/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240529153432-be2c8ac0a840 h1:DKub+sG+vfKqwOCaKrthhJA/bP7gTZWxbdrFV86Q5Ms=
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20240529153432-be2c8ac0a840/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240124081123-f90cfc88a1dc h1:GUZlr25hXLu/PeASqm8P5dPOyD4CdfvkzyEtXEBLbr8= github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240124081123-f90cfc88a1dc h1:GUZlr25hXLu/PeASqm8P5dPOyD4CdfvkzyEtXEBLbr8=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240124081123-f90cfc88a1dc/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y= github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240124081123-f90cfc88a1dc/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240523161247-6f16d12c5a86 h1:PN1WSt3u/DEIn4hX5Oqrm9bm5nf5VBfenfXmbX4mg60= github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240523161247-6f16d12c5a86 h1:PN1WSt3u/DEIn4hX5Oqrm9bm5nf5VBfenfXmbX4mg60=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240523161247-6f16d12c5a86/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y= github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240523161247-6f16d12c5a86/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240529153442-f5fb416605f5 h1:ZhrzpAjIUZHD6gSKPA8zwHjIys9/GTGN3hPKtwMORSA=
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20240529153442-f5fb416605f5/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -6,8 +6,6 @@
package link package link
import ( import (
"errors"
r "github.com/waku-org/go-zerokit-rln-apple/rln" r "github.com/waku-org/go-zerokit-rln-apple/rln"
) )
@ -96,8 +94,7 @@ func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
} }
func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) { func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) {
return nil, errors.New("not implemented") return i.ffi.GenerateRLNProofWithWitness(input)
//return i.ffi.GenerateRLNProofWithWitness(input)
} }
func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) { func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) {

View File

@ -5,8 +5,6 @@
package link package link
import ( import (
"errors"
r "github.com/waku-org/go-zerokit-rln-arm/rln" r "github.com/waku-org/go-zerokit-rln-arm/rln"
) )
@ -95,8 +93,7 @@ func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
} }
func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) { func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) {
return nil, errors.New("not implemented") return i.ffi.GenerateRLNProofWithWitness(input)
//return i.ffi.GenerateRLNProofWithWitness(input)
} }
func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) { func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) {

View File

@ -6,8 +6,6 @@
package link package link
import ( import (
"errors"
r "github.com/waku-org/go-zerokit-rln-x86_64/rln" r "github.com/waku-org/go-zerokit-rln-x86_64/rln"
) )
@ -96,8 +94,7 @@ func (i RLNWrapper) GenerateRLNProof(input []byte) ([]byte, error) {
} }
func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) { func (i RLNWrapper) GenerateRLNProofWithWitness(input []byte) ([]byte, error) {
return nil, errors.New("not implemented") return i.ffi.GenerateRLNProofWithWitness(input)
//return i.ffi.GenerateRLNProofWithWitness(input)
} }
func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) { func (i RLNWrapper) VerifyWithRoots(input []byte, roots []byte) (bool, error) {

View File

@ -266,53 +266,73 @@ func (r *RLN) GenerateProof(
} }
// Returns a RLN proof with a custom witness, so no tree is required in the RLN instance // Returns a RLN proof with a custom witness, so no tree is required in the RLN instance
// to calculate such proof. The witness can be created with GetMerkleProof data // to calculate such proof. The witness can be created with GetMerkleProof data.
// input [ id_secret_hash<32> | num_elements<8> | path_elements<var1> | num_indexes<8> | path_indexes<var2> | x<32> | epoch<32> | rln_identifier<32> ]
// output [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> ]
func (r *RLN) GenerateRLNProofWithWitness(witness RLNWitnessInput) (*RateLimitProof, error) { func (r *RLN) GenerateRLNProofWithWitness(witness RLNWitnessInput) (*RateLimitProof, error) {
// TODO: Will be implemented once custom witness is supported in RLN v2 // serialized as: https://github.com/vacp2p/zerokit/blob/v0.5.0/rln/src/protocol.rs#L127
return nil, errors.New("not implemented") // input [ id_secret_hash<32> | user_message_limit<32> | message_id<32> | num_elements<8> | path_elements<var1> | num_indexes<8> | path_indexes<var2> | external_nullifier<32> ]
proofBytes, err := r.w.GenerateRLNProofWithWitness(witness.serialize()) proofBytes, err := r.w.GenerateRLNProofWithWitness(witness.serialize())
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(proofBytes) != 320 { expectedBytes := 288
return nil, errors.New("invalid proof generated") if len(proofBytes) != expectedBytes {
return nil, fmt.Errorf("invalid proof generated. size: %d expected: %d",
len(proofBytes), expectedBytes)
} }
// parse the proof as [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> ] // parse proof taken from: https://github.com/vacp2p/zerokit/blob/v0.5.0/rln/src/public.rs#L750
// [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32>]
proofOffset := 128 proofOffset := 128
rootOffset := proofOffset + 32 rootOffset := proofOffset + 32
epochOffset := rootOffset + 32 externalNullifierOffset := rootOffset + 32
shareXOffset := epochOffset + 32 shareXOffset := externalNullifierOffset + 32
shareYOffset := shareXOffset + 32 shareYOffset := shareXOffset + 32
nullifierOffset := shareYOffset + 32 nullifierOffset := shareYOffset + 32
rlnIdentifierOffset := nullifierOffset + 32
var zkproof ZKSNARK var zkproof ZKSNARK
var proofRoot, shareX, shareY MerkleNode var proofRoot, shareX, shareY MerkleNode
var epochR Epoch var externalNullifier Nullifier
var nullifier Nullifier var nullifier Nullifier
var rlnIdentifier RLNIdentifier
copy(zkproof[:], proofBytes[0:proofOffset]) copy(zkproof[:], proofBytes[0:proofOffset])
copy(proofRoot[:], proofBytes[proofOffset:rootOffset]) copy(proofRoot[:], proofBytes[proofOffset:rootOffset])
copy(epochR[:], proofBytes[rootOffset:epochOffset]) copy(externalNullifier[:], proofBytes[rootOffset:externalNullifierOffset])
copy(shareX[:], proofBytes[epochOffset:shareXOffset]) copy(shareX[:], proofBytes[externalNullifierOffset:shareXOffset])
copy(shareY[:], proofBytes[shareXOffset:shareYOffset]) copy(shareY[:], proofBytes[shareXOffset:shareYOffset])
copy(nullifier[:], proofBytes[shareYOffset:nullifierOffset]) copy(nullifier[:], proofBytes[shareYOffset:nullifierOffset])
copy(rlnIdentifier[:], proofBytes[nullifierOffset:rlnIdentifierOffset])
return &RateLimitProof{ return &RateLimitProof{
Proof: zkproof, Proof: zkproof,
MerkleRoot: proofRoot, MerkleRoot: proofRoot,
ShareX: shareX, ExternalNullifier: externalNullifier,
ShareY: shareY, ShareX: shareX,
Nullifier: nullifier, ShareY: shareY,
Nullifier: nullifier,
}, nil }, nil
}
func (r *RLN) CreateWitness(
idSecretHash IDSecretHash,
userMessageLimit uint32,
messageId uint32,
data []byte,
epoch [32]byte,
merkleProof MerkleProof) (RLNWitnessInput, error) {
externalNullifier, err := r.Poseidon(epoch[:], RLN_IDENTIFIER[:])
if err != nil {
return RLNWitnessInput{}, fmt.Errorf("could not construct the external nullifier: %w", err)
}
return RLNWitnessInput{
IDSecretHash: idSecretHash,
UserMessageLimit: userMessageLimit,
MessageId: messageId,
MerkleProof: merkleProof,
X: HashToBN255(data),
ExternalNullifier: externalNullifier,
}, nil
} }
func serialize32(roots [][32]byte) []byte { func serialize32(roots [][32]byte) []byte {

View File

@ -432,8 +432,9 @@ func (s *RLNSuite) TestGetMerkleProof() {
} }
func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesOK() { func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesOK() {
s.T().Skip("Skipped until proof generation with witness is implemented for RLNv2")
treeSize := 20 treeSize := 20
userMessageLimit := uint32(100)
message := []byte("some rln protected message")
rln, err := NewRLN() rln, err := NewRLN()
s.NoError(err) s.NoError(err)
@ -442,7 +443,7 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesOK() {
// Create a Merkle tree with random members // Create a Merkle tree with random members
for i := 0; i < treeSize; i++ { for i := 0; i < treeSize; i++ {
memberKeys, err := rln.MembershipKeyGen() memberKeys, err := rln.MembershipKeyGen(userMessageLimit)
s.NoError(err) s.NoError(err)
err = rln.InsertMember(memberKeys.IDCommitment, memberKeys.UserMessageLimit) err = rln.InsertMember(memberKeys.IDCommitment, memberKeys.UserMessageLimit)
@ -450,8 +451,8 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesOK() {
treeElements = append(treeElements, *memberKeys) treeElements = append(treeElements, *memberKeys)
} }
// We generate proofs with a custom witness aquired outside zerokit for diferent indexes // For different leafs (with a custom witness)
for _, memberIndex := range []uint{0, 10, 13, 15} { for _, memberIndex := range []uint{0, 10, 13} {
root, err := rln.GetMerkleRoot() root, err := rln.GetMerkleRoot()
s.NoError(err) s.NoError(err)
@ -459,45 +460,48 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesOK() {
merkleProof, err := rln.GetMerkleProof(memberIndex) merkleProof, err := rln.GetMerkleProof(memberIndex)
s.NoError(err) s.NoError(err)
message := []byte("some rln protected message") // For different epochs
epoch := ToEpoch(1000) for _, epoch := range []Epoch{ToEpoch(1), ToEpoch(9998765)} {
rlnWitness := CreateWitness( // For some possible message ids
treeElements[memberIndex].IDSecretHash, for _, messageId := range []uint32{0, 50, 99} {
message,
epoch,
merkleProof)
// Generate a proof with our custom witness (Merkle Path of the memberIndex) rlnWitness, err := rln.CreateWitness(
proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness) treeElements[memberIndex].IDSecretHash,
s.NoError(err) userMessageLimit,
verified1, err := rln.Verify(message, *proofRes1, root) messageId,
s.NoError(err) message,
s.True(verified1) epoch,
merkleProof)
s.NoError(err)
// message sequence within the epoch // Generate a proof with our custom witness (Merkle Path of the memberIndex)
messageId := uint32(1) proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness)
s.NoError(err)
verified1, err := rln.Verify(message, *proofRes1, root)
s.NoError(err)
s.True(verified1)
// Generate a proof without our custom witness, to ensure they match // Generate a proof without our custom witness, to ensure they match
proofRes2, err := rln.GenerateProof(message, treeElements[memberIndex], MembershipIndex(memberIndex), epoch, messageId) proofRes2, err := rln.GenerateProof(message, treeElements[memberIndex], MembershipIndex(memberIndex), epoch, messageId)
s.NoError(err) s.NoError(err)
// Ensure we have the same root // Ensure we have the same root
s.Equal(root, proofRes1.MerkleRoot) s.Equal(root, proofRes1.MerkleRoot)
// Proof generate with custom witness match the proof generate with the witness // Proof generate with custom witness match the proof generate with the witness
// from zerokit. Proof itself is not asserted, can be different. // from zerokit. Proof itself is not asserted, can be different.
s.Equal(proofRes1.MerkleRoot, proofRes2.MerkleRoot) s.Equal(proofRes1.MerkleRoot, proofRes2.MerkleRoot)
//s.Equal(proofRes1.Epoch, proofRes2.Epoch) s.Equal(proofRes1.ExternalNullifier, proofRes2.ExternalNullifier)
s.Equal(proofRes1.ShareX, proofRes2.ShareX) s.Equal(proofRes1.ShareX, proofRes2.ShareX)
s.Equal(proofRes1.ShareY, proofRes2.ShareY) s.Equal(proofRes1.ShareY, proofRes2.ShareY)
s.Equal(proofRes1.Nullifier, proofRes2.Nullifier) s.Equal(proofRes1.Nullifier, proofRes2.Nullifier)
//s.Equal(proofRes1.RLNIdentifier, proofRes2.RLNIdentifier) }
}
} }
} }
func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() { func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() {
s.T().Skip("Skipped until proof generation with witness is implemented for RLNv2")
treeSize := 20 treeSize := 20
@ -528,11 +532,17 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() {
message := []byte("some rln protected message") message := []byte("some rln protected message")
epoch := ToEpoch(1000) epoch := ToEpoch(1000)
rlnWitness1 := CreateWitness( userMessageLimit := uint32(10)
messageId := uint32(1)
rlnWitness1, err := rln.CreateWitness(
treeElements[memberIndex].IDSecretHash, treeElements[memberIndex].IDSecretHash,
userMessageLimit,
messageId,
message, message,
epoch, epoch,
merkleProof) merkleProof)
s.NoError(err)
// Generate a proof with our custom witness (Merkle Path of the memberIndex) // Generate a proof with our custom witness (Merkle Path of the memberIndex)
proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness1) proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness1)
@ -543,19 +553,23 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() {
s.NoError(err) s.NoError(err)
s.False(verified1) s.False(verified1)
// 2) Different epoch, does not verify // 2) Different nullifier (epoch or rln id), does not verify
//proofRes1.Epoch = ToEpoch(999) proofRes1.ExternalNullifier = [32]byte{0x11}
verified2, err := rln.Verify(message, *proofRes1, root) verified2, err := rln.Verify(message, *proofRes1, root)
s.NoError(err) s.NoError(err)
s.False(verified2) s.False(verified2)
// 3) Merkle proof in provided witness is wrong, does not verify // 3) Merkle proof in provided witness is wrong, does not verify
merkleProof.PathElements[0] = [32]byte{0x11} merkleProof.PathElements[0] = [32]byte{0x11}
rlnWitness2 := CreateWitness(
rlnWitness2, err := rln.CreateWitness(
treeElements[memberIndex].IDSecretHash, treeElements[memberIndex].IDSecretHash,
userMessageLimit,
messageId,
message, message,
epoch, epoch,
merkleProof) merkleProof)
s.NoError(err)
proofRes3, err := rln.GenerateRLNProofWithWitness(rlnWitness2) proofRes3, err := rln.GenerateRLNProofWithWitness(rlnWitness2)
s.NoError(err) s.NoError(err)
@ -573,11 +587,14 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() {
s.NoError(err) s.NoError(err)
// Proof proves memberIndex inclusion, but provided membership is different // Proof proves memberIndex inclusion, but provided membership is different
rlnWitness4 := CreateWitness( rlnWitness4, err := rln.CreateWitness(
memberKeys.IDSecretHash, memberKeys.IDSecretHash,
userMessageLimit,
messageId,
[]byte("some rln protected message"), []byte("some rln protected message"),
ToEpoch(999), ToEpoch(999),
merkleProof4) merkleProof4)
s.NoError(err)
proofRes4, err := rln.GenerateRLNProofWithWitness(rlnWitness4) proofRes4, err := rln.GenerateRLNProofWithWitness(rlnWitness4)
s.NoError(err) s.NoError(err)
@ -585,6 +602,20 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness_VerifiesNOK() {
verified4, err := rln.Verify(message, *proofRes4, root) verified4, err := rln.Verify(message, *proofRes4, root)
s.NoError(err) s.NoError(err)
s.False(verified4) s.False(verified4)
// 5) Message id goes beyond the userMessageLimit, does not generate
wrongMessageId := uint32(1000)
rlnWitness5, err := rln.CreateWitness(
treeElements[memberIndex].IDSecretHash,
userMessageLimit,
wrongMessageId,
message,
epoch,
merkleProof)
s.NoError(err)
_, err = rln.GenerateRLNProofWithWitness(rlnWitness5)
s.Error(err)
} }
} }

View File

@ -59,14 +59,22 @@ func (r RateLimitProof) serialize() []byte {
return proofBytes return proofBytes
} }
// serialize converts a RLNWitnessInput to a byte seq
// [ id_secret_hash<32> | user_message_limit<32> | message_id<32> | num_elements<8> | path_elements<var1> | num_indexes<8> | path_indexes<var2> | external_nullifier<32> ]
func (r *RLNWitnessInput) serialize() []byte { func (r *RLNWitnessInput) serialize() []byte {
output := make([]byte, 0) output := make([]byte, 0)
var userMessageLimitByte [32]byte
var messageIdByte [32]byte
binary.LittleEndian.PutUint32(userMessageLimitByte[0:], r.UserMessageLimit)
binary.LittleEndian.PutUint32(messageIdByte[0:], r.MessageId)
output = append(output, r.IDSecretHash[:]...) output = append(output, r.IDSecretHash[:]...)
output = append(output, userMessageLimitByte[:]...)
output = append(output, messageIdByte[:]...)
output = append(output, r.MerkleProof.serialize()...) output = append(output, r.MerkleProof.serialize()...)
output = append(output, r.X[:]...) output = append(output, r.X[:]...)
output = append(output, r.Epoch[:]...) output = append(output, r.ExternalNullifier[:]...)
output = append(output, r.RlnIdentifier[:]...)
return output return output
} }

View File

@ -52,13 +52,14 @@ func TestRLNWitnessInputSerDe(t *testing.T) {
} }
witness := RLNWitnessInput{ witness := RLNWitnessInput{
IDSecretHash: random32(), IDSecretHash: random32(),
MerkleProof: mProof, UserMessageLimit: 8,
X: [32]byte{0x00}, MessageId: 7,
Epoch: ToEpoch(10), MerkleProof: mProof,
RlnIdentifier: [32]byte{0x00}, X: [32]byte{0x00},
ExternalNullifier: [32]byte{0x00},
} }
ser := witness.serialize() ser := witness.serialize()
require.Equal(t, 32+8+depth*32+depth+8+32+32+32, len(ser)) require.Equal(t, 32+32+32+8+depth*32+depth+8+32+32, len(ser))
} }

View File

@ -73,13 +73,14 @@ type MerkleProof struct {
PathIndexes []uint8 `json:"pathIndexes"` PathIndexes []uint8 `json:"pathIndexes"`
} }
// Equivalent: https://github.com/vacp2p/zerokit/blob/v0.3.5/rln/src/protocol.rs#L33-L40 // Equivalent: https://github.com/vacp2p/zerokit/blob/v0.5.0/rln/src/protocol.rs#L35
type RLNWitnessInput struct { type RLNWitnessInput struct {
IDSecretHash IDSecretHash `json:"identitySecretHash"` IDSecretHash IDSecretHash `json:"identitySecretHash"`
MerkleProof MerkleProof `json:"merkleProof"` UserMessageLimit uint32 `json:"userMessageLimit"`
X [32]byte `json:"x"` MessageId uint32 `json:"messageId"`
Epoch Epoch `json:"epoch"` MerkleProof MerkleProof `json:"merkleProof"`
RlnIdentifier RLNIdentifier `json:"rlnIdentifier"` X [32]byte `json:"x"`
ExternalNullifier Nullifier `json:"externalNullifier"`
} }
type TreeDepth int type TreeDepth int

View File

@ -11,21 +11,6 @@ import (
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
func CreateWitness(
idSecretHash IDSecretHash,
data []byte,
epoch [32]byte,
merkleProof MerkleProof) RLNWitnessInput {
return RLNWitnessInput{
IDSecretHash: idSecretHash,
MerkleProof: merkleProof,
X: HashToBN255(data),
Epoch: epoch,
RlnIdentifier: RLN_IDENTIFIER,
}
}
func ToIdentityCredentials(groupKeys [][]string) ([]IdentityCredential, error) { func ToIdentityCredentials(groupKeys [][]string) ([]IdentityCredential, error) {
// groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format // groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format
// the toIdentityCredentials proc populates a sequence of IdentityCredentials using the supplied groupKeys // the toIdentityCredentials proc populates a sequence of IdentityCredentials using the supplied groupKeys