Some refactors

This commit is contained in:
alrevuelta 2024-01-23 14:13:12 +01:00
parent 28a98ba8c0
commit 86d2d24525
No known key found for this signature in database
GPG Key ID: F345C9F3CCDB886E
6 changed files with 40 additions and 54 deletions

View File

@ -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

View File

@ -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)

View File

@ -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++ {

View File

@ -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},
} }

View File

@ -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?
} }

View File

@ -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