mirror of
https://github.com/logos-messaging/go-zerokit-rln.git
synced 2026-01-02 05:03:10 +00:00
Custom witness proof with RLN v2 (#22)
This commit is contained in:
parent
54bb48f178
commit
84d12e61d9
6
go.mod
6
go.mod
@ -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
8
go.sum
@ -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=
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
64
rln/rln.go
64
rln/rln.go
@ -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 {
|
||||||
|
|||||||
107
rln/rln_test.go
107
rln/rln_test.go
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
13
rln/types.go
13
rln/types.go
@ -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
|
||||||
|
|||||||
15
rln/utils.go
15
rln/utils.go
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user