mirror of
https://github.com/logos-messaging/go-zerokit-rln.git
synced 2026-01-02 13:13:11 +00:00
Some refactors
This commit is contained in:
parent
28a98ba8c0
commit
86d2d24525
38
rln/rln.go
38
rln/rln.go
@ -10,6 +10,10 @@ import (
|
|||||||
"github.com/waku-org/go-zerokit-rln/rln/link"
|
"github.com/waku-org/go-zerokit-rln/rln/link"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Same as: https://github.com/vacp2p/zerokit/blob/v0.3.5/rln/src/public.rs#L35
|
||||||
|
// Prevents a RLN ZK proof generated for one application to be re-used in another one.
|
||||||
|
var RLN_IDENTIFIER = [32]byte{166, 140, 43, 8, 8, 22, 206, 113, 151, 128, 118, 40, 119, 197, 218, 174, 11, 117, 84, 228, 96, 211, 212, 140, 145, 104, 146, 99, 24, 192, 217, 4}
|
||||||
|
|
||||||
// RLN represents the context used for rln.
|
// RLN represents the context used for rln.
|
||||||
type RLN struct {
|
type RLN struct {
|
||||||
w *link.RLNWrapper
|
w *link.RLNWrapper
|
||||||
@ -130,17 +134,14 @@ func (r *RLN) SeededMembershipKeyGen(seed []byte) (*IdentityCredential, error) {
|
|||||||
|
|
||||||
// appendLength returns length prefixed version of the input with the following format
|
// appendLength returns length prefixed version of the input with the following format
|
||||||
// [len<8>|input<var>], the len is a 8 byte value serialized in little endian
|
// [len<8>|input<var>], the len is a 8 byte value serialized in little endian
|
||||||
|
|
||||||
func appendLength(input []byte) []byte {
|
func appendLength(input []byte) []byte {
|
||||||
inputLen := make([]byte, 8)
|
inputLen := make([]byte, 8)
|
||||||
binary.LittleEndian.PutUint64(inputLen, uint64(len(input)))
|
binary.LittleEndian.PutUint64(inputLen, uint64(len(input)))
|
||||||
return append(inputLen, input...)
|
return append(inputLen, input...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// can i reuse serialize32??
|
// Similar to appendLength but for 32 byte values. The length that is prepended is
|
||||||
// TODO: dirty
|
// the length of elements that are 32 bytes long each
|
||||||
// Assume that the input is a sequence of 32 byte values
|
|
||||||
// so length is the amount of 32 byte values
|
|
||||||
func appendLength32(input []byte) []byte {
|
func appendLength32(input []byte) []byte {
|
||||||
inputLen := make([]byte, 8)
|
inputLen := make([]byte, 8)
|
||||||
binary.LittleEndian.PutUint64(inputLen, uint64(len(input)/32))
|
binary.LittleEndian.PutUint64(inputLen, uint64(len(input)/32))
|
||||||
@ -242,32 +243,12 @@ func (r *RLN) GenerateProof(data []byte, key IdentityCredential, index Membershi
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// input :
|
// 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
|
||||||
identity_secret: Fr,
|
// input [ id_secret_hash<32> | num_elements<8> | path_elements<var1> | num_indexes<8> | path_indexes<var2> | x<32> | epoch<32> | rln_identifier<32> ]
|
||||||
path_elements: Vec<Fr>, | 8 * 20*32 + 20 + 8
|
|
||||||
identity_path_index: Vec<u8>, | --
|
|
||||||
x: Fr, -> this seems to be of fixed size? not size+ variablelenarray
|
|
||||||
epoch: Fr,
|
|
||||||
rln_identifier: Fr,
|
|
||||||
*/
|
|
||||||
// todo: output same as other function.
|
|
||||||
// output [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<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: this shouldn go here but i think there is an issue in zerokit
|
|
||||||
fmt.Println("len data before ", len(witness.Data))
|
|
||||||
// Remove its not a poseidon hash but kekkack
|
|
||||||
hashedData, err := r.Poseidon(witness.Data[:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//witness.Data = hashedData[:]
|
|
||||||
_ = hashedData
|
|
||||||
|
|
||||||
fmt.Println("len data after ", len(witness.Data))
|
|
||||||
|
|
||||||
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
|
||||||
@ -277,7 +258,6 @@ func (r *RLN) GenerateRLNProofWithWitness(witness RLNWitnessInput) (*RateLimitPr
|
|||||||
return nil, errors.New("invalid proof generated")
|
return nil, errors.New("invalid proof generated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: maybe move this into a common function (used by the other generateRlnproof function)
|
|
||||||
// parse the proof as [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> ]
|
// parse the proof as [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> ]
|
||||||
proofOffset := 128
|
proofOffset := 128
|
||||||
rootOffset := proofOffset + 32
|
rootOffset := proofOffset + 32
|
||||||
|
|||||||
@ -355,6 +355,8 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness() {
|
|||||||
rln, err := NewRLN()
|
rln, err := NewRLN()
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
|
||||||
|
// TODO: Run multiple test with multiple indexes
|
||||||
|
|
||||||
// Leaf we generate the proof for
|
// Leaf we generate the proof for
|
||||||
memberIndex := uint(4)
|
memberIndex := uint(4)
|
||||||
memKeys, err := rln.MembershipKeyGen()
|
memKeys, err := rln.MembershipKeyGen()
|
||||||
@ -380,39 +382,30 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness() {
|
|||||||
// TODO: Add some asserts on roots
|
// TODO: Add some asserts on roots
|
||||||
fmt.Println("root from zerokit: ", root)
|
fmt.Println("root from zerokit: ", root)
|
||||||
|
|
||||||
// Inputs for proof generation
|
|
||||||
msg := []byte("hi there")
|
|
||||||
var epoch = Epoch([32]byte{0x00, 0x00, 0x00, 0x00, 0x01})
|
|
||||||
|
|
||||||
// We provide out custom witness
|
// We provide out custom witness
|
||||||
merkleProof, err := rln.GetMerkleProof(memberIndex)
|
merkleProof, err := rln.GetMerkleProof(memberIndex)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
|
||||||
// TODO: This should be abstracted away, move inside somewhere
|
message := []byte("some rln protected message")
|
||||||
x := HashToBN255(msg)
|
epoch := ToEpoch(1000)
|
||||||
|
rlnWitness := CreateWitness(
|
||||||
rlnWitness := RLNWitnessInput{
|
*memKeys,
|
||||||
// memberIndex key
|
message,
|
||||||
IdentityCredential: *memKeys,
|
epoch,
|
||||||
MerkleProof: merkleProof,
|
merkleProof)
|
||||||
Data: x[:], // TODO: This is not really data, its a hash of data
|
|
||||||
Epoch: epoch,
|
|
||||||
RlnIdentifier: [32]byte{166, 140, 43, 8, 8, 22, 206, 113, 151, 128, 118, 40, 119, 197, 218, 174, 11, 117, 84, 228, 96, 211, 212, 140, 145, 104, 146, 99, 24, 192, 217, 4}, // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(rlnWitness)
|
proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
verified1, err := rln.Verify(msg[:], *proofRes1, root)
|
verified1, err := rln.Verify(message, *proofRes1, root)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
s.True(verified1)
|
s.True(verified1)
|
||||||
|
|
||||||
proofRes2, err := rln.GenerateProof(msg[:], *memKeys, MembershipIndex(memberIndex), epoch)
|
proofRes2, err := rln.GenerateProof(message, *memKeys, MembershipIndex(memberIndex), epoch)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
|
||||||
// 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
|
// from zerokit. Proof itself is not asserted, can be different.
|
||||||
//s.Equal(proofRes1.Proof, proofRes2.Proof) // The proof itself can be different
|
|
||||||
s.Equal(proofRes1.MerkleRoot, proofRes2.MerkleRoot)
|
s.Equal(proofRes1.MerkleRoot, proofRes2.MerkleRoot)
|
||||||
s.Equal(proofRes1.Epoch, proofRes2.Epoch)
|
s.Equal(proofRes1.Epoch, proofRes2.Epoch)
|
||||||
s.Equal(proofRes1.ShareX, proofRes2.ShareX)
|
s.Equal(proofRes1.ShareX, proofRes2.ShareX)
|
||||||
|
|||||||
@ -53,7 +53,7 @@ func (r *RLNWitnessInput) serialize() []byte {
|
|||||||
|
|
||||||
output = append(output, r.IdentityCredential.IDSecretHash[:]...)
|
output = append(output, r.IdentityCredential.IDSecretHash[:]...)
|
||||||
output = append(output, r.MerkleProof.serialize()...)
|
output = append(output, r.MerkleProof.serialize()...)
|
||||||
output = append(output, r.Data...) // TODO: Data doesnt have the lend prepended. Is it fixed to 32 bytes? Different than in other places
|
output = append(output, r.X[:]...)
|
||||||
output = append(output, r.Epoch[:]...)
|
output = append(output, r.Epoch[:]...)
|
||||||
output = append(output, r.RlnIdentifier[:]...)
|
output = append(output, r.RlnIdentifier[:]...)
|
||||||
|
|
||||||
@ -115,8 +115,6 @@ func (r *MerkleProof) deserialize(b []byte) error {
|
|||||||
numElements.String(), numIndexes.String()))
|
numElements.String(), numIndexes.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Depth check, but currently not accesible
|
|
||||||
|
|
||||||
r.PathIndexes = make([]uint8, numIndexes.Uint64())
|
r.PathIndexes = make([]uint8, numIndexes.Uint64())
|
||||||
|
|
||||||
for i := uint64(0); i < numIndexes.Uint64(); i++ {
|
for i := uint64(0); i < numIndexes.Uint64(); i++ {
|
||||||
|
|||||||
@ -47,7 +47,6 @@ func TestMerkleProofSerDe(t *testing.T) {
|
|||||||
func TestRLNWitnessInputSerDe(t *testing.T) {
|
func TestRLNWitnessInputSerDe(t *testing.T) {
|
||||||
// TODO: Is data size arbitrary? or fixed to 32. How its decode in zerokit seems to be fixed to 32.
|
// TODO: Is data size arbitrary? or fixed to 32. How its decode in zerokit seems to be fixed to 32.
|
||||||
// At least in the proof with custom witness function.
|
// At least in the proof with custom witness function.
|
||||||
data := [32]byte{0x00}
|
|
||||||
depth := 20
|
depth := 20
|
||||||
|
|
||||||
mProof := MerkleProof{
|
mProof := MerkleProof{
|
||||||
@ -65,7 +64,7 @@ func TestRLNWitnessInputSerDe(t *testing.T) {
|
|||||||
IDSecretHash: random32(),
|
IDSecretHash: random32(),
|
||||||
},
|
},
|
||||||
MerkleProof: mProof,
|
MerkleProof: mProof,
|
||||||
Data: data[:],
|
X: [32]byte{0x00},
|
||||||
Epoch: ToEpoch(10),
|
Epoch: ToEpoch(10),
|
||||||
RlnIdentifier: [32]byte{0x00},
|
RlnIdentifier: [32]byte{0x00},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,13 +68,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
|
||||||
type RLNWitnessInput struct {
|
type RLNWitnessInput struct {
|
||||||
// TODO: Maybe dont store the whole IdentityCredential and just the secret
|
// TODO: Maybe dont store the whole IdentityCredential and just the secret
|
||||||
IdentityCredential IdentityCredential `json:"identityCredential"`
|
IdentityCredential IdentityCredential `json:"identityCredential"`
|
||||||
MerkleProof MerkleProof `json:"merkleProof"`
|
MerkleProof MerkleProof `json:"merkleProof"`
|
||||||
|
|
||||||
// This is not the data but the hashed version of it "x"..TODO rename and reconsider
|
// This is not the data but the hashed version of it "x"..TODO rename and reconsider
|
||||||
Data []byte `json:"data"` // TODO: this should be fixed 32
|
X [32]byte `json:"x"`
|
||||||
Epoch Epoch `json:"epoch"`
|
Epoch Epoch `json:"epoch"`
|
||||||
RlnIdentifier RLNIdentifier `json:"rlnIdentifier"` // what is this? TOOD: app specific. which one is ours?
|
RlnIdentifier RLNIdentifier `json:"rlnIdentifier"` // what is this? TOOD: app specific. which one is ours?
|
||||||
}
|
}
|
||||||
|
|||||||
15
rln/utils.go
15
rln/utils.go
@ -8,6 +8,21 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func CreateWitness(
|
||||||
|
identityCredential IdentityCredential, // TODO only the secret hash.
|
||||||
|
data []byte,
|
||||||
|
epoch [32]byte,
|
||||||
|
merkleProof MerkleProof) RLNWitnessInput {
|
||||||
|
|
||||||
|
return RLNWitnessInput{
|
||||||
|
IdentityCredential: identityCredential,
|
||||||
|
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