mirror of
https://github.com/logos-messaging/go-zerokit-rln.git
synced 2026-01-02 13:13:11 +00:00
Verify works now
This commit is contained in:
parent
85a45dc73a
commit
28a98ba8c0
5
go.mod
5
go.mod
@ -3,21 +3,22 @@ module github.com/waku-org/go-zerokit-rln
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/consensys/gnark-crypto v0.12.1
|
||||
github.com/ethereum/go-ethereum v1.13.10
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/waku-org/go-zerokit-rln-apple v0.0.0-20240117094748-68b4162e8fd7
|
||||
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
|
||||
golang.org/x/crypto v0.18.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bits-and-blooms/bitset v1.10.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/holiman/uint256 v1.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
9
go.sum
9
go.sum
@ -1,6 +1,10 @@
|
||||
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
|
||||
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
|
||||
github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
@ -11,11 +15,9 @@ github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoI
|
||||
github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA=
|
||||
github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
|
||||
github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
@ -33,6 +35,5 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -377,80 +377,51 @@ func (s *RLNSuite) TestGenerateRLNProofWithWitness() {
|
||||
root, err := rln.GetMerkleRoot()
|
||||
s.NoError(err)
|
||||
|
||||
// TODO: Add some asserts on roots
|
||||
fmt.Println("root from zerokit: ", root)
|
||||
|
||||
// Inputs for proof generation
|
||||
msg := [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0}
|
||||
//msg := [32]byte{69, 7, 140, 46, 26, 131, 147, 30, 161, 68, 2, 5, 234, 195, 227, 223, 119, 187, 116, 97, 153, 70, 71, 254, 60, 149, 54, 109, 77, 79, 105, 20}
|
||||
msg := []byte("hi there")
|
||||
var epoch = Epoch([32]byte{0x00, 0x00, 0x00, 0x00, 0x01})
|
||||
|
||||
// We provide out custom witness
|
||||
merkleProof, err := rln.GetMerkleProof(memberIndex)
|
||||
s.NoError(err)
|
||||
|
||||
//hashMsg, err := rln.Poseidon(msg[:])
|
||||
//s.NoError(err)
|
||||
hashMsg := [32]byte{69, 7, 140, 46, 26, 131, 147, 30, 161, 68, 2, 5, 234, 195, 227, 223, 119, 187, 116, 97, 153, 70, 71, 254, 60, 149, 54, 109, 77, 79, 105, 20}
|
||||
// TODO: This should be abstracted away, move inside somewhere
|
||||
x := HashToBN255(msg)
|
||||
|
||||
rlnWitness := RLNWitnessInput{
|
||||
// memberIndex key
|
||||
IdentityCredential: *memKeys,
|
||||
MerkleProof: merkleProof,
|
||||
Data: hashMsg[:],
|
||||
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
|
||||
}
|
||||
|
||||
fmt.Println("Witness secrethash ", rlnWitness.IdentityCredential.IDSecretHash)
|
||||
fmt.Println("Witness merkle path", rlnWitness.MerkleProof.PathElements)
|
||||
fmt.Println("Witness merkle indexes", rlnWitness.MerkleProof.PathIndexes)
|
||||
fmt.Println("Witness data", rlnWitness.Data)
|
||||
fmt.Println("Witness epoch", rlnWitness.Epoch)
|
||||
fmt.Println("Witness rln identifier", rlnWitness.RlnIdentifier)
|
||||
|
||||
// generate proof
|
||||
proofRes, err := rln.GenerateRLNProofWithWitness(rlnWitness)
|
||||
// Generate a proof with our custom witness (Merkle Path of the memberIndex)
|
||||
proofRes1, err := rln.GenerateRLNProofWithWitness(rlnWitness)
|
||||
s.NoError(err)
|
||||
|
||||
//proofRes.ShareX = dataToReplace
|
||||
|
||||
fmt.Println("Proof Epoch: ", proofRes)
|
||||
|
||||
// TODO: for testing. proof without witness (are proofs deterministic? maybe not)
|
||||
proofRes2, err := rln.GenerateProof(msg[:], *memKeys, MembershipIndex(memberIndex), epoch)
|
||||
s.NoError(err)
|
||||
|
||||
fmt.Println("Proof1 Epoch: ", proofRes2.Epoch)
|
||||
fmt.Println("Proof1 Nullifier: ", proofRes2.Nullifier)
|
||||
fmt.Println("Proof1 ShareX: ", proofRes2.ShareX)
|
||||
fmt.Println("Proof1 ShareY: ", proofRes2.ShareY)
|
||||
fmt.Println("Proof1 MerkleRoot: ", proofRes2.MerkleRoot)
|
||||
fmt.Println("Proof1 RlnIdentifier: ", proofRes2.RLNIdentifier)
|
||||
|
||||
fmt.Println("Proof Epoch: ", proofRes.Epoch)
|
||||
fmt.Println("Proof Nullifier: ", proofRes.Nullifier)
|
||||
fmt.Println("Proof ShareX: ", proofRes.ShareX)
|
||||
fmt.Println("Proof ShareY: ", proofRes.ShareY)
|
||||
fmt.Println("Proof MerkleRoot: ", proofRes.MerkleRoot)
|
||||
fmt.Println("Proof RlnIdentifier: ", proofRes.RLNIdentifier)
|
||||
|
||||
// Verifty old proofs
|
||||
verified1, err := rln.Verify(msg[:], *proofRes2, root)
|
||||
verified1, err := rln.Verify(msg[:], *proofRes1, root)
|
||||
s.NoError(err)
|
||||
s.True(verified1)
|
||||
|
||||
// verify the proof with the witness
|
||||
//msg := [32]byte{0x00, 0x00, 0x01}
|
||||
//verified, err := rln.Verify([]byte{0x00, 0x00, 0x01}, *proofRes, root)
|
||||
verified, err := rln.Verify(msg[:], *proofRes, root)
|
||||
proofRes2, err := rln.GenerateProof(msg[:], *memKeys, MembershipIndex(memberIndex), epoch)
|
||||
s.NoError(err)
|
||||
|
||||
_ = verified
|
||||
// TODO: Not working
|
||||
s.True(verified)
|
||||
// Proof generate with custom witness match the proof generate with the witness
|
||||
// from zerokit
|
||||
//s.Equal(proofRes1.Proof, proofRes2.Proof) // The proof itself can be different
|
||||
s.Equal(proofRes1.MerkleRoot, proofRes2.MerkleRoot)
|
||||
s.Equal(proofRes1.Epoch, proofRes2.Epoch)
|
||||
s.Equal(proofRes1.ShareX, proofRes2.ShareX)
|
||||
s.Equal(proofRes1.ShareY, proofRes2.ShareY)
|
||||
s.Equal(proofRes1.Nullifier, proofRes2.Nullifier)
|
||||
s.Equal(proofRes1.RLNIdentifier, proofRes2.RLNIdentifier)
|
||||
|
||||
// TODO: test a proof that shall not be verified
|
||||
// TODO: generate multiple proofs with random data
|
||||
}
|
||||
|
||||
func (s *RLNSuite) TestEpochConsistency() {
|
||||
|
||||
@ -74,7 +74,7 @@ type RLNWitnessInput struct {
|
||||
MerkleProof MerkleProof `json:"merkleProof"`
|
||||
|
||||
// This is not the data but the hashed version of it "x"..TODO rename and reconsider
|
||||
Data []byte `json:"data"`
|
||||
Data []byte `json:"data"` // TODO: this should be fixed 32
|
||||
Epoch Epoch `json:"epoch"`
|
||||
RlnIdentifier RLNIdentifier `json:"rlnIdentifier"` // what is this? TOOD: app specific. which one is ours?
|
||||
}
|
||||
|
||||
47
rln/utils.go
47
rln/utils.go
@ -2,9 +2,9 @@ package rln
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
@ -110,38 +110,19 @@ func Bytes32ToBigInt(value [32]byte) *big.Int {
|
||||
return result
|
||||
}
|
||||
|
||||
func EndianConvertTODO(data []byte) [32]byte {
|
||||
// Hashes a byte array to a field element in BN254, as used by zerokit.
|
||||
// Equivalent to: https://github.com/vacp2p/zerokit/blob/v0.3.4/rln/src/hashers.rs
|
||||
func HashToBN255(data []byte) [32]byte {
|
||||
// Hash is fixed to 32 bytes
|
||||
hashed := crypto.Keccak256(data[:])
|
||||
|
||||
hashGoEth := crypto.Keccak256(data[:])
|
||||
_ = hashGoEth
|
||||
//if len(hashGoEth) != 32 {
|
||||
// fmt.Println("errorrrrrr")
|
||||
// }
|
||||
myHash32 := [32]byte{}
|
||||
// copy(myHash32[:], hashGoEth)
|
||||
// Convert to field element
|
||||
var frBN254 fr.Element
|
||||
frBN254.Unmarshal(revert(hashed))
|
||||
frBN254Bytes := frBN254.Bytes()
|
||||
|
||||
// el hash esta controlado por ahora
|
||||
copy(myHash32[:], data)
|
||||
|
||||
fmt.Println("inpit is: ", data)
|
||||
fmt.Println("hash is: ", myHash32)
|
||||
|
||||
var uintVals [4]uint64
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
chunk := make([]byte, 8)
|
||||
copy(chunk, myHash32[i*8:(i+1)*8])
|
||||
fmt.Println("chunk is: ", chunk)
|
||||
|
||||
myBig := new(big.Int)
|
||||
myBig.SetBytes(revert(chunk))
|
||||
fmt.Println("big is: ", myBig)
|
||||
uintVals[i] = myBig.Uint64()
|
||||
}
|
||||
|
||||
fmt.Println("uintVals is: ", uintVals)
|
||||
|
||||
returnthis := [32]byte{}
|
||||
|
||||
return returnthis
|
||||
// Return fixed size
|
||||
fixexLen := [32]byte{}
|
||||
copy(fixexLen[:], revert(frBN254Bytes[:]))
|
||||
return fixexLen
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -45,100 +43,13 @@ func TestFlatten(t *testing.T) {
|
||||
out3 := Flatten(in3)
|
||||
require.Equal(t, expected3, out3)
|
||||
}
|
||||
|
||||
func TestTODO(t *testing.T) {
|
||||
func TestHashToBN255(t *testing.T) {
|
||||
// Inputs for proof generation
|
||||
msg := []byte{72, 7, 140, 254, 213, 99, 57, 234, 84, 150, 46, 114, 195, 124, 127, 88, 143, 196, 248, 229, 188, 23, 56, 39, 186, 117, 203, 16, 166, 58, 150, 165}
|
||||
msg := []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
|
||||
conv := EndianConvertTODO(msg)
|
||||
|
||||
fmt.Println(conv)
|
||||
|
||||
ints := []uint64{16877630849297418056, 6376952776256034388, 2826034866254562447, 11931788747685459386}
|
||||
|
||||
fmt.Println(ints[0])
|
||||
|
||||
str := ""
|
||||
for i, _ := range ints {
|
||||
str = str + padBinaryString(uint64ToBinaryString(ints[4-i-1]), 64)
|
||||
}
|
||||
|
||||
fmt.Println("-- ", str)
|
||||
|
||||
byteArray, err := binaryStringToBytes(str)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
myBigInt := new(big.Int)
|
||||
myBigInt.SetBytes(byteArray[:])
|
||||
|
||||
fmt.Println("mybigint", myBigInt.String())
|
||||
|
||||
fmt.Println(byteArray)
|
||||
|
||||
// Expected
|
||||
// in := [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0}
|
||||
// hashed: []byte{72, 7, 140, 254, 213, 99, 57, 234, 84, 150, 46, 114, 195, 124, 127, 88, 143, 196, 248, 229, 188, 23, 56, 39, 186, 117, 203, 16, 166, 58, 150, 165}
|
||||
// expected := [32]byte{69, 7, 140, 46, 26, 131, 147, 30, 161, 68, 2, 5, 234, 195, 227, 223, 119, 187, 116, 97, 153, 70, 71, 254, 60, 149, 54, 109, 77, 79, 105, 20}
|
||||
}
|
||||
|
||||
func reverseString(input string) string {
|
||||
// Convert string to a slice of runes
|
||||
runes := []rune(input)
|
||||
|
||||
// Reverse the order of runes
|
||||
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
||||
runes[i], runes[j] = runes[j], runes[i]
|
||||
}
|
||||
|
||||
// Convert the slice of runes back to a string
|
||||
reversedString := string(runes)
|
||||
|
||||
return reversedString
|
||||
}
|
||||
|
||||
func binaryStringToBytes(binaryString string) ([32]byte, error) {
|
||||
var byteArray [32]byte
|
||||
|
||||
// Ensure the binary string has 256 bits (32 bytes)
|
||||
if len(binaryString) != 256 {
|
||||
return byteArray, fmt.Errorf("binary string must have exactly 256 bits")
|
||||
}
|
||||
|
||||
// Iterate over 32 chunks of 8 bits each and parse them to bytes
|
||||
for i := 0; i < 32; i++ {
|
||||
startIndex := i * 8
|
||||
endIndex := startIndex + 8
|
||||
bits := binaryString[startIndex:endIndex]
|
||||
|
||||
// Parse the 8-bit chunk to a byte
|
||||
byteValue, err := strconv.ParseUint(bits, 2, 8)
|
||||
if err != nil {
|
||||
return byteArray, err
|
||||
}
|
||||
|
||||
byteArray[i] = byte(byteValue)
|
||||
}
|
||||
|
||||
return byteArray, nil
|
||||
}
|
||||
|
||||
func padBinaryString(binaryString string, length int) string {
|
||||
// Calculate padding length
|
||||
paddingLength := length - len(binaryString)
|
||||
|
||||
// Pad with zeros
|
||||
paddedBinaryString := strings.Repeat("0", paddingLength) + binaryString
|
||||
|
||||
return paddedBinaryString
|
||||
}
|
||||
|
||||
func bigIntToBinaryString(num *big.Int) string {
|
||||
return fmt.Sprintf("%b", num)
|
||||
}
|
||||
|
||||
func uint64ToBinaryString(num uint64) string {
|
||||
return strconv.FormatUint(num, 2)
|
||||
out := HashToBN255(msg)
|
||||
fmt.Println("out: ", out)
|
||||
require.Equal(t,
|
||||
[32]byte{69, 7, 140, 46, 26, 131, 147, 30, 161, 68, 2, 5, 234, 195, 227, 223, 119, 187, 116, 97, 153, 70, 71, 254, 60, 149, 54, 109, 77, 79, 105, 20},
|
||||
out)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user