diff --git a/testdata/proof1.json b/testdata/proof1.json new file mode 100644 index 0000000..045c3d8 --- /dev/null +++ b/testdata/proof1.json @@ -0,0 +1,6 @@ +{ + "a": ["0x1dca74fcf694ed936db05adcdef51b3c2014764e99c5703d5e69d76c87810422","0x2c9ba9c02cf6955ca2c772664df5768a7b0cc77576d7e9b81e095fb3c08b9c16"], + "b": [["0x0aa0f61f43f154d035a48f348789a16f5d4005f76467691f974a8a2e8edb1742","0x026e7e1392d435dd3e73ea37add798405d5cd48f8721f9573c12a2c51258ec8b"],["0x303d397f66efd9dce45e5de04637b106870a7e057d183184939bd44fab28a431","0x257512bdc1bba713498a5981ccc2d5bb833a8cc6e5981e3d71a37fbac31e8b0b"]], + "c": ["0x07a8feff8de7347c93685684dd4e8854fc02a64b221602f6b0afe9b5bf6e1e01","0x258e96099adc2ba4411009449e714eaf112a4fe6afefdb85ff06c36db83adb43"], + "public": ["6"] +} diff --git a/testdata/public0.json b/testdata/public0.json new file mode 100644 index 0000000..2d8d3ed --- /dev/null +++ b/testdata/public0.json @@ -0,0 +1,3 @@ +[ + "6" +] diff --git a/testdata/public1.json b/testdata/public1.json new file mode 100644 index 0000000..2691759 --- /dev/null +++ b/testdata/public1.json @@ -0,0 +1 @@ +["6"] diff --git a/testdata/vk1.json b/testdata/vk1.json new file mode 100644 index 0000000..5697c7d --- /dev/null +++ b/testdata/vk1.json @@ -0,0 +1 @@ +{"alpha_g1":["0x1cf86a02b7de239051e6c51ceeef1d8a5d2089e9a2f7cbc5c6074f5fd2b0d777","0x041778937c8a6268ddc1b4eb4912f9edb017e22d8701f91b053d7b05c2f1471a"],"beta_g1":["0x154706ec1e025b39e8bfb4d1d223df46ed7b7458e1575c075f3c9501c6c2115e","0x2b80a63d18b3f22b729d86c8f1bf49a374b0871d5342f8fc1eabea301222f224"],"beta_g2":[["0x2039525c2c75b0c369bbd397481e8321ab82ee611c0ecde9ad64501395b65bb6","0x20d752b48b87705ee8e036a1c21afc80ce1fbf08fc61eb54fe840f0bc2d28704"],["0x17e4c8fb30585247872275e139da64316745190ffcd123a90484a85502d27c5f","0x04ad1008299254713101063744973903c9bdba5ab3c4def72331a53f9e45b261"]],"delta_g1":["0x1e87e5fa36ceb48346448d7bde273bf0e68b938068714ae5b9a34b5f06189ba5","0x0c39864a5a4e5f1dc74c0ec7235f36bdefc7f1a5c34277fbbab675210e1456f8"],"delta_g2":[["0x202d1f6118c936b072d21ee1c39326b72950e342c29e28770abbbe82bf6f9bfc","0x122bedfe76fd47a7d9af22c48acce6e39542c4e639234cd21f8dcf1ad857d2a1"],["0x216d0c805652dbb0ab1d46aad44f4230a614ec4eec8c8bdae84c94b94d1e30be","0x0cf19a6f199fd19aa2aed4e78c8813201e7821a3e4d7d94897639e0630f8e406"]],"gamma_g2":[["0x06119f2fc5e0c76f9722417fedb2a267385e63a5f48c37684e379790db770d4b","0x220a1e37e224859a0d4af6f29f9909f84b02dfed9b29bd376e94f44964379d70"],["0x02ba5f26131b4787569ae4075f817a8b395de987f3887fe5c55cefa4a00c1d29","0x139b91c637580b238cde5e6d0e3472a21453a9394fd9e35dfb0b343a0f9c9880"]],"ic":[["0x0e480b0119f8eaeaeb944752f1ae2ff13da7b78fdd0b04d5fa12e1422d1d8a29","0x153471558ba605e153a9b6230f14dfad9e401c0313e7ac0917e27ce26aa69fd0"],["0x062a1efbae92eef025288ecb23437f1ad3edc9aa490ec33d8a3dde5f09d8a66b","0x18eab07ce28c80f7c49bbcbdb5e3f6c8c61651f13230742a7eb25b0efa830332"]],"input_names":["main.r"]} diff --git a/verifier.go b/verifier.go index d2c243a..1178508 100644 --- a/verifier.go +++ b/verifier.go @@ -102,7 +102,8 @@ func stringToBigInt(s string) *big.Int { return n } -func parsePublicRaw(pj []byte) ([]*big.Int, error) { +// ParsePublicRaw takes a json []byte and outputs the []*big.Int struct +func ParsePublicRaw(pj []byte) ([]*big.Int, error) { var pr []string err := json.Unmarshal(pj, &pr) if err != nil { @@ -191,3 +192,26 @@ func proofRawToProof(pr ProofRaw) (*Proof, error) { return &p, nil } + +var q = stringToBigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617") + +// Verify performs the Groth16 zkSnark verification +func Verify(vk *Vk, proof *Proof, inputs []*big.Int) bool { + if len(inputs)+1 != len(vk.GammaABC) { + fmt.Println("len(inputs)+1 != len(vk.GammaABC)") + return false + } + vkX := new(bn256.G1).ScalarBaseMult(stringToBigInt("0")) + for i := 0; i < len(inputs); i++ { + // check input inside field + if inputs[0].Cmp(q) != -1 { + return false + } + vkX = new(bn256.G1).Add(vkX, new(bn256.G1).ScalarMult(vk.GammaABC[i+1], inputs[i])) + } + vkX = new(bn256.G1).Add(vkX, vk.GammaABC[0]) + + g1 := []*bn256.G1{proof.A, vk.Alpha.Neg(vk.Alpha), vkX.Neg(vkX), proof.C.Neg(proof.C)} + g2 := []*bn256.G2{proof.B, vk.Beta, vk.Gamma, vk.Delta} + return bn256.PairingCheck(g1, g2) +} diff --git a/verifier_test.go b/verifier_test.go index 67d2efc..7ebf1e4 100644 --- a/verifier_test.go +++ b/verifier_test.go @@ -60,3 +60,61 @@ func TestParseProof(t *testing.T) { assert.Equal(t, "bn256.G2((2275d97dce5445433ec7bc6d01c35f0afad9afcf6f3350cd15eeef1023242c01, 0b5f21c2d981916cd5e1037b446b170b6c60dd184fdbb3381b7d0880fb48300d), (2c2a08a60032f536afbcb21c079b563cdce68b7ef906e973c52f574121a95df0, 1690100372c53776b60c0ee56926debb4d0acee90f7952ecc63861e0269a098a))", vk.Beta.String()) assert.Equal(t, "bn256.G2((15c9b1123841897787badbe858eb00943fc8a99454666f21acf4e79e13547471, 2d0c4fa1239184802aeda1f206e49104940aa3eccc1b3e0141c25b2dba8e7caf), (2bc9bc381cf68badd992338c637b36b54936b69cb8560eaf5a8cbe2c20ff8522, 256ad09ecb0abc15fd48f20c37d28ffcf0f8eb3b23cb10cdeee7365b598963ac))", vk.Gamma.String()) } + +func TestVerify0(t *testing.T) { + proofJson, err := ioutil.ReadFile("testdata/proof0.json") + require.Nil(t, err) + vkJson, err := ioutil.ReadFile("testdata/vk0.json") + require.Nil(t, err) + publicJson, err := ioutil.ReadFile("testdata/public0.json") + require.Nil(t, err) + + public, err := ParsePublicRaw(publicJson) + require.Nil(t, err) + proof, err := ParseProofRaw(proofJson) + require.Nil(t, err) + vk, err := ParseVkRaw(vkJson) + require.Nil(t, err) + + v := Verify(vk, proof, public) + assert.True(t, v) +} + +func TestVerify1(t *testing.T) { + proofJson, err := ioutil.ReadFile("testdata/proof1.json") + require.Nil(t, err) + vkJson, err := ioutil.ReadFile("testdata/vk1.json") + require.Nil(t, err) + publicJson, err := ioutil.ReadFile("testdata/public1.json") + require.Nil(t, err) + + public, err := ParsePublicRaw(publicJson) + require.Nil(t, err) + proof, err := ParseProofRaw(proofJson) + require.Nil(t, err) + vk, err := ParseVkRaw(vkJson) + require.Nil(t, err) + + v := Verify(vk, proof, public) + assert.True(t, v) +} + +func BenchmarkVerify(b *testing.B) { + proofJson, err := ioutil.ReadFile("testdata/proof0.json") + require.Nil(b, err) + vkJson, err := ioutil.ReadFile("testdata/vk0.json") + require.Nil(b, err) + publicJson, err := ioutil.ReadFile("testdata/public0.json") + require.Nil(b, err) + + public, err := ParsePublicRaw(publicJson) + require.Nil(b, err) + proof, err := ParseProofRaw(proofJson) + require.Nil(b, err) + vk, err := ParseVkRaw(vkJson) + require.Nil(b, err) + + for i := 0; i < b.N; i++ { + Verify(vk, proof, public) + } +}