mirror of
https://github.com/logos-storage/gnark-plonky2-verifier.git
synced 2026-01-04 06:03:12 +00:00
Cleanup repo for release
This commit is contained in:
parent
b19cd390f1
commit
6e9f1a7c50
17
README.md
17
README.md
@ -1,15 +1,6 @@
|
||||
# gnark-plonky2-verifier
|
||||
|
||||
# gnark-ed25519
|
||||
ed25519 implementation in Gnark
|
||||
|
||||
To test:
|
||||
To run the benchmark,
|
||||
```
|
||||
go test gnark-ed25519/edwards_curve
|
||||
```
|
||||
|
||||
To build and run:
|
||||
```
|
||||
go build gnark-ed25519 && ./gnark-ed25519
|
||||
```
|
||||
|
||||
if it panics on compilation.... make vriables capitalzie
|
||||
go run benchmark.go
|
||||
```
|
||||
74
cubic.go
74
cubic.go
@ -1,74 +0,0 @@
|
||||
// Copyright 2020 ConsenSys AG
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "os"
|
||||
// "github.com/consensys/gnark/frontend"
|
||||
// "github.com/consensys/gnark-crypto/ecc"
|
||||
// "github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
// "github.com/consensys/gnark/backend/groth16"
|
||||
// _ "gnark-ed25519/edwards_curve"
|
||||
// _ "gnark-ed25519/sha512"
|
||||
// )
|
||||
|
||||
// // Circuit defines a simple circuit
|
||||
// // x**3 + x + 5 == y
|
||||
// type Circuit struct {
|
||||
// // struct tags on a variable is optional
|
||||
// // default uses variable name and secret visibility.
|
||||
// X frontend.Variable `gnark:"x"`
|
||||
// Y frontend.Variable `gnark:",public"`
|
||||
// }
|
||||
|
||||
// // Define declares the circuit constraints
|
||||
// // x**3 + x + 5 == y
|
||||
// func (circuit *Circuit) Define(api frontend.API) error {
|
||||
// x3 := api.Mul(circuit.X, circuit.X, circuit.X)
|
||||
// api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5))
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func main() {
|
||||
// err := mainImpl()
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func mainImpl() error {
|
||||
// var myCircuit Circuit
|
||||
// r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &myCircuit)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// assignment := &Circuit{
|
||||
// X: "2",
|
||||
// Y: "15",
|
||||
// }
|
||||
// witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
// publicWitness, _ := witness.Public()
|
||||
// pk, vk, err := groth16.Setup(r1cs)
|
||||
// proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
// err = groth16.Verify(proof, vk, publicWitness)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// fmt.Println(proof)
|
||||
// return nil
|
||||
// }
|
||||
277
ed25519.go
277
ed25519.go
@ -1,277 +0,0 @@
|
||||
// Copyright 2020 ConsenSys AG
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gnark-ed25519/poseidon"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
"github.com/consensys/gnark/test"
|
||||
)
|
||||
|
||||
// type Eddsa25519Circuit struct {
|
||||
// M []frontend.Variable
|
||||
// Pk []frontend.Variable
|
||||
// Sig []frontend.Variable
|
||||
// }
|
||||
|
||||
// func (circuit *Eddsa25519Circuit) Define(api frontend.API) error {
|
||||
// c, err := edwards_curve.New[edwards_curve.Ed25519, edwards_curve.Ed25519Scalars](api)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// edwards_curve.CheckValid(c, circuit.Sig, circuit.M, circuit.Pk)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// type Sha512Circuit struct {
|
||||
// in []frontend.Variable `gnark:"in"`
|
||||
// out []frontend.Variable `gnark:"out"`
|
||||
// }
|
||||
|
||||
// func (circuit *Sha512Circuit) Define(api frontend.API) error {
|
||||
// res := sha512.Sha512(api, circuit.in)
|
||||
// if len(res) != 512 {
|
||||
// panic("bad length")
|
||||
// }
|
||||
// for i := 0; i < 512; i++ {
|
||||
// api.AssertIsEqual(res[i], circuit.out[i])
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func main() {
|
||||
// err := mainImpl()
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // func mainImpl() error {
|
||||
// // in := bytesToBits([]byte("Succinct Labs"))
|
||||
// // out := hexToBits("503ace098aa03f6feec1b5df0a38aee923f744a775508bc81f2b94ad139be297c2e8cd8c44af527b5d3f017a7fc929892c896604047e52e3f518924f52bff0dc")
|
||||
|
||||
// // myCircuit := Sha512Circuit{
|
||||
// // in,
|
||||
// // out,
|
||||
// // }
|
||||
// // fmt.Println(time.Now(), "compiling...")
|
||||
// // r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &myCircuit)
|
||||
// // if err != nil {
|
||||
// // return err
|
||||
// // }
|
||||
|
||||
// // assignment := &Sha512Circuit{
|
||||
// // in,
|
||||
// // out,
|
||||
// // }
|
||||
// // fmt.Println(time.Now(), "generating witness...")
|
||||
// // witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
// // publicWitness, _ := witness.Public()
|
||||
// // fmt.Println(time.Now(), "groth setup...")
|
||||
// // pk, vk, err := groth16.Setup(r1cs)
|
||||
// // fmt.Println(time.Now(), "groth prove...")
|
||||
// // proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
// // fmt.Println(time.Now(), "groth verify...")
|
||||
// // err = groth16.Verify(proof, vk, publicWitness)
|
||||
// // if err != nil {
|
||||
// // return err
|
||||
// // }
|
||||
// // fmt.Println(proof)
|
||||
// // return nil
|
||||
// // }
|
||||
|
||||
// func mainImpl() error {
|
||||
// M := "53756363696e6374204c616273"
|
||||
// Pk := "f7ec1c43f4de9d49556de87b86b26a98942cb078486fdb44de38b80864c39731"
|
||||
// Sig := "35c323757c20640a294345c89c0bfcebe3d554fdb0c7b7a0bdb72222c531b1ec849fed99a053e0f5b02dd9a25bb6eb018885526d9f583cdbde0b1e9f6329da09"
|
||||
|
||||
// myCircuit := Eddsa25519Circuit{
|
||||
// M: hexToBits(M),
|
||||
// Pk: hexToBits(Pk),
|
||||
// Sig: hexToBits(Sig),
|
||||
// }
|
||||
// fmt.Println(time.Now(), "compiling...")
|
||||
// r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &myCircuit)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// assignment := &Eddsa25519Circuit{
|
||||
// M: hexToBits(M),
|
||||
// Pk: hexToBits(Pk),
|
||||
// Sig: hexToBits(Sig),
|
||||
// }
|
||||
// fmt.Println(time.Now(), "generating witness...")
|
||||
// witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
// publicWitness, _ := witness.Public()
|
||||
// fmt.Println(time.Now(), "groth setup...")
|
||||
// pk, vk, err := groth16.Setup(r1cs)
|
||||
// fmt.Println(time.Now(), "groth prove...")
|
||||
// proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
// fmt.Println(time.Now(), "groth verify...")
|
||||
// err = groth16.Verify(proof, vk, publicWitness)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// fmt.Println(proof)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func hexToBits(h string) []frontend.Variable {
|
||||
// b, err := hex.DecodeString(h)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// result := make([]frontend.Variable, len(b)*8)
|
||||
// for i, v := range b {
|
||||
// for j := 0; j < 8; j++ {
|
||||
// if (v & (1 << j)) != 0 {
|
||||
// result[i*8+j] = 1
|
||||
// } else {
|
||||
// result[i*8+j] = 0
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result
|
||||
// }
|
||||
|
||||
// func bytesToBits(arr []byte) []frontend.Variable {
|
||||
// result := make([]frontend.Variable, len(arr)*8)
|
||||
// for i, v := range arr {
|
||||
// for j := 0; j < 8; j++ {
|
||||
// if (v & (1 << (7 - j))) != 0 {
|
||||
// result[i*8+j] = 1
|
||||
// } else {
|
||||
// result[i*8+j] = 0
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result
|
||||
// }
|
||||
|
||||
type PoseidonCircuit struct {
|
||||
In [12]frontend.Variable
|
||||
Out [12]frontend.Variable
|
||||
}
|
||||
|
||||
func (circuit *PoseidonCircuit) Define(api frontend.API) error {
|
||||
poseidon.Poseidon(api, circuit.In, circuit.Out)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
in_str := [12]string{
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
}
|
||||
out_str := [12]string{
|
||||
"4330397376401421145",
|
||||
"14124799381142128323",
|
||||
"8742572140681234676",
|
||||
"14345658006221440202",
|
||||
"15524073338516903644",
|
||||
"5091405722150716653",
|
||||
"15002163819607624508",
|
||||
"2047012902665707362",
|
||||
"16106391063450633726",
|
||||
"4680844749859802542",
|
||||
"15019775476387350140",
|
||||
"1698615465718385111",
|
||||
}
|
||||
|
||||
var in [12]big.Int
|
||||
var out [12]big.Int
|
||||
for i := 0; i < 12; i++ {
|
||||
n := new(big.Int)
|
||||
n, _ = n.SetString(in_str[i], 10)
|
||||
in[i] = *n
|
||||
}
|
||||
for i := 0; i < 12; i++ {
|
||||
n := new(big.Int)
|
||||
n, _ = n.SetString(out_str[i], 10)
|
||||
out[i] = *n
|
||||
}
|
||||
|
||||
var _in [12]frontend.Variable
|
||||
var _out [12]frontend.Variable
|
||||
|
||||
for i := 0; i < 12; i++ {
|
||||
_in[i] = in[i]
|
||||
_out[i] = out[i]
|
||||
}
|
||||
|
||||
myCircuit := PoseidonCircuit{
|
||||
In: _in,
|
||||
Out: _out,
|
||||
}
|
||||
|
||||
fmt.Println(time.Now(), "compiling...")
|
||||
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &myCircuit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
assignment := &PoseidonCircuit{
|
||||
In: _in,
|
||||
Out: _out,
|
||||
}
|
||||
|
||||
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
publicWitness, err := witness.Public()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(time.Now(), "groth setup...")
|
||||
pk, vk, err := groth16.Setup(r1cs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = test.IsSolved(&myCircuit, assignment, ecc.BN254.ScalarField())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(time.Now(), "groth prove...")
|
||||
proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(time.Now(), "groth verify...")
|
||||
|
||||
err = groth16.Verify(proof, vk, publicWitness)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,297 +0,0 @@
|
||||
package edwards_curve
|
||||
|
||||
|
||||
// This file is little-endian
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/std/math/emulated"
|
||||
"gnark-ed25519/sha512"
|
||||
)
|
||||
|
||||
|
||||
func H(api frontend.API, m []frontend.Variable) []frontend.Variable {
|
||||
rawResult := sha512.Sha512(api, swapByteEndianness(m))
|
||||
sResult := swapByteEndianness(rawResult[:])
|
||||
return sResult
|
||||
}
|
||||
|
||||
func pow2(n uint) *big.Int {
|
||||
result := big.NewInt(1)
|
||||
result.Lsh(result, n)
|
||||
return result
|
||||
}
|
||||
|
||||
type EdCurve = Curve[Ed25519, Ed25519Scalars]
|
||||
type EdPoint = AffinePoint[Ed25519]
|
||||
type EdCoordinate = emulated.Element[Ed25519]
|
||||
type EdScalar = emulated.Element[Ed25519Scalars]
|
||||
|
||||
func bits_to_scalar(c *EdCurve, s []frontend.Variable) EdCoordinate {
|
||||
if len(s) != 256 { panic("bad length") }
|
||||
elt := emulated.NewElement[Ed25519](0)
|
||||
if len(elt.Limbs) != 4 { panic("bad length") }
|
||||
i := 0
|
||||
for k := 0; k < 4; k++ {
|
||||
elt.Limbs[k] = c.api.FromBinary(s[i:i+64]...)
|
||||
i += 64
|
||||
}
|
||||
if i != len(s) { panic("bad length") }
|
||||
return elt
|
||||
}
|
||||
|
||||
// func bits_to_clamped_scalar(c *EdCurve, input []frontend.Variable) EdScalar {
|
||||
// if len(input) != 256 { panic("bad length") }
|
||||
// s := make([]frontend.Variable, len(input))
|
||||
// copy(s, input)
|
||||
// s[0] = 0
|
||||
// s[1] = 0
|
||||
// s[2] = 0
|
||||
// s[254] = 1
|
||||
// return bits_to_scalar[Ed25519Scalars](c, s)
|
||||
// }
|
||||
|
||||
func bits_to_element(c *EdCurve, input []frontend.Variable) EdPoint {
|
||||
// L := emulated.NewElement[Ed25519Scalars](rEd25519)
|
||||
unchecked_point := decodepoint(c, input)
|
||||
|
||||
// // TODO: https://github.com/warner/python-pure25519 says this check is not necessary:
|
||||
// //
|
||||
// // > This library is conservative, and performs full subgroup-membership checks on decoded
|
||||
// // > points, which adds considerable overhead. The Curve25519/Ed25519 algorithms were
|
||||
// // > designed to not require these checks, so a careful application might be able to
|
||||
// // > improve on this slightly (Ed25519 verify down to 6.2ms, DH-finish to 3.2ms).
|
||||
// c.AssertIsZero(c.ScalarMul(unchecked_point, L))
|
||||
|
||||
return unchecked_point
|
||||
}
|
||||
|
||||
// func publickey(c *EdCurve, seed []frontend.Variable) EdPoint {
|
||||
// if len(seed) != 32 { panic("bad length") }
|
||||
// a := bits_to_clamped_scalar(c, H(c.api, seed)[:256])
|
||||
// return c.ScalarMul(c.g, a)
|
||||
// }
|
||||
|
||||
func CheckValid(c *EdCurve, s, m, pk []frontend.Variable) {
|
||||
if len(s) != 512 { panic("bad signature length") }
|
||||
if len(pk) != 256 { panic("bad public key length") }
|
||||
if len(m) % 8 != 0 { panic("bad message length") }
|
||||
R := bits_to_element(c, s[:256])
|
||||
A := bits_to_element(c, pk)
|
||||
h := H(c.api, concat(s[:256], pk, m))
|
||||
v1 := c.ScalarMulBinary(c.g, s[256:])
|
||||
v2 := c.Add(R, c.ScalarMulBinary(A, h))
|
||||
c.AssertIsEqual(v1, v2)
|
||||
}
|
||||
|
||||
func reverse[T interface{}](arr []T) []T {
|
||||
result := make([]T, len(arr))
|
||||
for i, v := range arr {
|
||||
result[len(result)-i-1] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func concat(args ...[]frontend.Variable) []frontend.Variable {
|
||||
result := []frontend.Variable{}
|
||||
for _, v := range args {
|
||||
result = append(result, v...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func decodepoint(c *EdCurve, unclamped []frontend.Variable) EdPoint {
|
||||
if len(unclamped) != 256 { panic("bad length") }
|
||||
|
||||
s := make([]frontend.Variable, len(unclamped))
|
||||
copy(s, unclamped)
|
||||
s[255] = 0
|
||||
y := bits_to_scalar(c, s)
|
||||
// unclamped = int(binascii.hexlify(s[:32][::-1]), 16)
|
||||
// clamp = (1 << 255) - 1
|
||||
// y = unclamped & clamp # clear MSB
|
||||
|
||||
x := xrecover(c, y)
|
||||
// x = xrecover(y)
|
||||
|
||||
xbits := c.baseApi.ToBinary(x)
|
||||
if len(xbits) != 256 { panic("bad length") }
|
||||
mismatch := c.api.Xor(xbits[0], unclamped[255])
|
||||
x = c.baseApi.Select(mismatch, c.baseApi.Neg(x), x).(EdCoordinate)
|
||||
// if bool(x & 1) != bool(unclamped & (1<<255)): x = Q-x
|
||||
|
||||
P := AffinePoint[Ed25519]{
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
// P = [x,y]
|
||||
|
||||
c.AssertIsOnCurve(P)
|
||||
// if not isoncurve(P): raise NotOnCurve("decoding point that is not on curve")
|
||||
|
||||
return P
|
||||
}
|
||||
|
||||
func toValue(s EdCoordinate) *big.Int {
|
||||
result := big.NewInt(0)
|
||||
placeValue := big.NewInt(1)
|
||||
for _, v := range s.Limbs {
|
||||
q := new(big.Int).Mul(placeValue, v.(*big.Int))
|
||||
result.Add(result, q)
|
||||
placeValue.Lsh(placeValue, Ed25519{}.BitsPerLimb())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func _const(x int64) EdCoordinate {
|
||||
return emulated.NewElement[Ed25519](big.NewInt(x))
|
||||
}
|
||||
|
||||
// Q = 2**255 - 19
|
||||
// L = 2**252 + 27742317777372353535851937790883648493
|
||||
// def inv(x):
|
||||
// return pow(x, Q-2, Q)
|
||||
// d = -121665 * inv(121666)
|
||||
// I = pow(2,(Q-1)//4,Q)
|
||||
|
||||
func xrecover(c *EdCurve, y EdCoordinate) EdCoordinate {
|
||||
Q := Ed25519{}.Modulus()
|
||||
I := emulated.NewElement[Ed25519](newBigInt("2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0"))
|
||||
|
||||
yy := c.baseApi.Mul(y, y)
|
||||
xx := c.baseApi.Div(
|
||||
c.baseApi.Sub(yy, _const(1)),
|
||||
c.baseApi.Add(c.baseApi.Mul(c.d, yy), _const(1)),
|
||||
).(EdCoordinate)
|
||||
// xx = (y*y-1) * inv(d*y*y+1)
|
||||
|
||||
power := new(big.Int).Add(Q, big.NewInt(3))
|
||||
power.Rsh(power, 3)
|
||||
x := pow(c, xx, power)
|
||||
// x = pow(xx,(Q+3)//8,Q)
|
||||
|
||||
matches := c.baseApi.IsZero(c.baseApi.Sub(
|
||||
c.baseApi.Mul(x, x),
|
||||
xx,
|
||||
))
|
||||
x = c.baseApi.Select(matches, x, c.baseApi.Mul(x, emulated.NewElement[Ed25519](I))).(EdCoordinate)
|
||||
// if (x*x - xx) % Q != 0: x = (x*I) % Q
|
||||
|
||||
odd := c.baseApi.ToBinary(x)[0]
|
||||
x = c.baseApi.Select(odd, c.baseApi.Neg(x), x).(EdCoordinate)
|
||||
// if x % 2 != 0: x = Q-x
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func pow(c *EdCurve, base EdCoordinate, exponent *big.Int) EdCoordinate {
|
||||
mul := base
|
||||
result := _const(1)
|
||||
for exponent.Sign() > 0 {
|
||||
if exponent.Bit(0) != 0 {
|
||||
result = c.baseApi.Mul(result, mul).(EdCoordinate)
|
||||
}
|
||||
mul = c.baseApi.Mul(mul, mul).(EdCoordinate)
|
||||
exponent.Rsh(exponent, 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func swapByteEndianness(in []frontend.Variable) []frontend.Variable {
|
||||
if len(in) % 8 != 0 { panic("must be a multiple of 8 bits") }
|
||||
result := make([]frontend.Variable, len(in))
|
||||
for i := 0; i < len(in); i += 8 {
|
||||
for j := 0; j < 8; j++ {
|
||||
result[i+j] = in[i+7-j]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// def checkvalid(s, m, pk):
|
||||
// if len(s) != 64: raise Exception("signature length is wrong")
|
||||
// if len(pk) != 32: raise Exception("public-key length is wrong")
|
||||
// R = bytes_to_element(s[:32])
|
||||
// A = bytes_to_element(pk)
|
||||
// S = bytes_to_scalar(s[32:])
|
||||
// h = Hint(s[:32] + pk + m)
|
||||
// v1 = Base.scalarmult(S)
|
||||
// v2 = R.add(A.scalarmult(h))
|
||||
// return v1==v2
|
||||
|
||||
// def publickey(seed):
|
||||
// # turn first half of SHA512(seed) into scalar, then into point
|
||||
// assert len(seed) == 32
|
||||
// a = bytes_to_clamped_scalar(H(seed)[:32])
|
||||
// A = Base.scalarmult(a)
|
||||
// return A.to_bytes()
|
||||
|
||||
// def bytes_to_scalar(s):
|
||||
// assert len(s) == 32, len(s)
|
||||
// return int(binascii.hexlify(s[::-1]), 16)
|
||||
|
||||
|
||||
// from pure25519.basic import (bytes_to_clamped_scalar,
|
||||
// bytes_to_scalar, scalar_to_bytes,
|
||||
// bytes_to_element, Base)
|
||||
// import hashlib, binascii
|
||||
|
||||
// def H(m):
|
||||
// return hashlib.sha512(m).digest()
|
||||
|
||||
// def Hint(m):
|
||||
// h = H(m)
|
||||
// return int(binascii.hexlify(h[::-1]), 16)
|
||||
|
||||
// def signature(m,sk,pk):
|
||||
// assert len(sk) == 32 # seed
|
||||
// assert len(pk) == 32
|
||||
// h = H(sk[:32])
|
||||
// a_bytes, inter = h[:32], h[32:]
|
||||
// a = bytes_to_clamped_scalar(a_bytes)
|
||||
// r = Hint(inter + m)
|
||||
// R = Base.scalarmult(r)
|
||||
// R_bytes = R.to_bytes()
|
||||
// S = r + Hint(R_bytes + pk + m) * a
|
||||
// return R_bytes + scalar_to_bytes(S)
|
||||
|
||||
// def checkvalid(s, m, pk):
|
||||
// if len(s) != 64: raise Exception("signature length is wrong")
|
||||
// if len(pk) != 32: raise Exception("public-key length is wrong")
|
||||
// R = bytes_to_element(s[:32])
|
||||
// A = bytes_to_element(pk)
|
||||
// S = bytes_to_scalar(s[32:])
|
||||
// h = Hint(s[:32] + pk + m)
|
||||
// v1 = Base.scalarmult(S)
|
||||
// v2 = R.add(A.scalarmult(h))
|
||||
// return v1==v2
|
||||
|
||||
// # wrappers
|
||||
|
||||
// import os
|
||||
|
||||
// def create_signing_key():
|
||||
// seed = os.urandom(32)
|
||||
// return seed
|
||||
// def create_verifying_key(signing_key):
|
||||
// return publickey(signing_key)
|
||||
|
||||
// def sign(skbytes, msg):
|
||||
// """Return just the signature, given the message and just the secret
|
||||
// key."""
|
||||
// if len(skbytes) != 32:
|
||||
// raise ValueError("Bad signing key length %d" % len(skbytes))
|
||||
// vkbytes = create_verifying_key(skbytes)
|
||||
// sig = signature(msg, skbytes, vkbytes)
|
||||
// return sig
|
||||
|
||||
// def verify(vkbytes, sig, msg):
|
||||
// if len(vkbytes) != 32:
|
||||
// raise ValueError("Bad verifying key length %d" % len(vkbytes))
|
||||
// if len(sig) != 64:
|
||||
// raise ValueError("Bad signature length %d" % len(sig))
|
||||
// rc = checkvalid(sig, msg, vkbytes)
|
||||
// if not rc:
|
||||
// raise ValueError("rc != 0", rc)
|
||||
// return True
|
||||
@ -1,65 +0,0 @@
|
||||
package edwards_curve
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/test"
|
||||
)
|
||||
|
||||
type Eddsa25519Circuit struct {
|
||||
m []frontend.Variable
|
||||
pk []frontend.Variable
|
||||
sig []frontend.Variable
|
||||
}
|
||||
|
||||
func (circuit *Eddsa25519Circuit) Define(api frontend.API) error {
|
||||
c, err := New[Ed25519, Ed25519Scalars](api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
CheckValid(c, circuit.sig, circuit.m, circuit.pk)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestEddsa25519(t *testing.T) {
|
||||
assert := test.NewAssert(t)
|
||||
|
||||
m := "53756363696e6374204c616273"
|
||||
pk := "f7ec1c43f4de9d49556de87b86b26a98942cb078486fdb44de38b80864c39731"
|
||||
sig := "35c323757c20640a294345c89c0bfcebe3d554fdb0c7b7a0bdb72222c531b1ec849fed99a053e0f5b02dd9a25bb6eb018885526d9f583cdbde0b1e9f6329da09"
|
||||
|
||||
circuit := Eddsa25519Circuit {
|
||||
m: hexToBits(m),
|
||||
pk: hexToBits(pk),
|
||||
sig: hexToBits(sig),
|
||||
}
|
||||
witness := Eddsa25519Circuit {
|
||||
m: hexToBits(m),
|
||||
pk: hexToBits(pk),
|
||||
sig: hexToBits(sig),
|
||||
}
|
||||
|
||||
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
func hexToBits(h string) []frontend.Variable {
|
||||
b, err := hex.DecodeString(h)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result := make([]frontend.Variable, len(b) * 8)
|
||||
for i, v := range b {
|
||||
for j := 0; j < 8; j++ {
|
||||
if (v & (1 << j)) != 0 {
|
||||
result[i*8+j] = 1
|
||||
} else {
|
||||
result[i*8+j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
package edwards_curve
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var (
|
||||
qEd25519, rEd25519 *big.Int
|
||||
)
|
||||
|
||||
func init() {
|
||||
// https://neuromancer.sk/std/other/Ed25519
|
||||
qEd25519 = newBigInt("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed")
|
||||
rEd25519 = newBigInt("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed")
|
||||
}
|
||||
|
||||
type Ed25519 struct{}
|
||||
|
||||
func (fp Ed25519) NbLimbs() uint { return 4 }
|
||||
func (fp Ed25519) BitsPerLimb() uint { return 64 }
|
||||
func (fp Ed25519) IsPrime() bool { return true }
|
||||
func (fp Ed25519) Modulus() *big.Int { return qEd25519 }
|
||||
func (fp Ed25519) Generator() (*big.Int, *big.Int) {
|
||||
return newBigInt("216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"),
|
||||
newBigInt("6666666666666666666666666666666666666666666666666666666666666658")
|
||||
}
|
||||
|
||||
type Ed25519Scalars struct{}
|
||||
|
||||
func (fp Ed25519Scalars) NbLimbs() uint { return 4 }
|
||||
func (fp Ed25519Scalars) BitsPerLimb() uint { return 64 }
|
||||
func (fp Ed25519Scalars) IsPrime() bool { return true }
|
||||
func (fp Ed25519Scalars) Modulus() *big.Int { return rEd25519 }
|
||||
|
||||
@ -1,201 +0,0 @@
|
||||
package edwards_curve
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/std/math/emulated"
|
||||
)
|
||||
|
||||
func New[T, S emulated.FieldParams](api frontend.API) (*Curve[T, S], error) {
|
||||
var t T
|
||||
var s S
|
||||
var gxb, gyb *big.Int
|
||||
var A, D *big.Int
|
||||
_, is_25519_t := any(t).(Ed25519)
|
||||
_, is_25519_s := any(s).(Ed25519Scalars)
|
||||
if is_25519_t && is_25519_s {
|
||||
// https://neuromancer.sk/std/other/Ed25519
|
||||
gxb = newBigInt("216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A")
|
||||
gyb = newBigInt("6666666666666666666666666666666666666666666666666666666666666658")
|
||||
A = newBigInt("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec")
|
||||
D = newBigInt("52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3")
|
||||
} else {
|
||||
return nil, fmt.Errorf("unknown curve")
|
||||
}
|
||||
return newCurve[T, S](
|
||||
api,
|
||||
emulated.NewElement[T](A),
|
||||
emulated.NewElement[T](D),
|
||||
emulated.NewElement[T](gxb),
|
||||
emulated.NewElement[T](gyb))
|
||||
}
|
||||
|
||||
func newBigInt(s string) *big.Int {
|
||||
result, success := new(big.Int).SetString(s, 16)
|
||||
if !success {
|
||||
panic("invalid bigint")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO: could also have a type constraint for curve parameters (fields,
|
||||
// equation and generator). But for now we don't do arbitrary curves.
|
||||
|
||||
type Curve[T, S emulated.FieldParams] struct {
|
||||
a emulated.Element[T]
|
||||
d emulated.Element[T]
|
||||
|
||||
// api is the native api, we construct it ourselves to be sure
|
||||
api frontend.API
|
||||
// baseApi is the api for point operations
|
||||
baseApi frontend.API
|
||||
// scalarApi is the api for scalar operations
|
||||
scalarApi frontend.API
|
||||
|
||||
g AffinePoint[T]
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) Generator() AffinePoint[T] {
|
||||
return c.g
|
||||
}
|
||||
|
||||
func newCurve[T, S emulated.FieldParams](api frontend.API, a, d, Gx, Gy emulated.Element[T]) (*Curve[T, S], error) {
|
||||
ba, err := emulated.NewField[T](api)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new base api: %w", err)
|
||||
}
|
||||
sa, err := emulated.NewField[S](api)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new scalar api: %w", err)
|
||||
}
|
||||
return &Curve[T, S]{
|
||||
a: a,
|
||||
d: d,
|
||||
api: api,
|
||||
baseApi: ba,
|
||||
scalarApi: sa,
|
||||
g: AffinePoint[T]{
|
||||
X: Gx,
|
||||
Y: Gy,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type AffinePoint[T emulated.FieldParams] struct {
|
||||
X, Y emulated.Element[T]
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) Neg(p AffinePoint[T]) AffinePoint[T] {
|
||||
return AffinePoint[T]{
|
||||
X: p.X,
|
||||
Y: c.baseApi.Neg(p.Y).(emulated.Element[T]),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) AssertIsEqual(p, q AffinePoint[T]) {
|
||||
c.baseApi.AssertIsEqual(p.X, q.X)
|
||||
c.baseApi.AssertIsEqual(p.Y, q.Y)
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) AssertIsOnCurve(p AffinePoint[T]) {
|
||||
xx := c.baseApi.Mul(p.X, p.X)
|
||||
yy := c.baseApi.Mul(p.Y, p.Y)
|
||||
axx := c.baseApi.Mul(xx, c.a)
|
||||
lhs := c.baseApi.Add(axx, yy)
|
||||
|
||||
dxx := c.baseApi.Mul(xx, c.d)
|
||||
dxxyy := c.baseApi.Mul(dxx, yy)
|
||||
rhs := c.baseApi.Add(dxxyy, 1)
|
||||
|
||||
c.baseApi.AssertIsEqual(lhs, rhs)
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) AssertIsZero(p AffinePoint[T]) {
|
||||
c.baseApi.AssertIsEqual(p.X, 0)
|
||||
c.baseApi.AssertIsEqual(p.Y, 1)
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) Add(q, r AffinePoint[T]) AffinePoint[T] {
|
||||
// u = (x1 + y1) * (x2 + y2)
|
||||
u1 := c.baseApi.Mul(q.X, c.a)
|
||||
u1 = c.baseApi.Sub(q.Y, u1)
|
||||
u2 := c.baseApi.Add(r.X, r.Y)
|
||||
u := c.baseApi.Mul(u1, u2)
|
||||
|
||||
// v0 = x1 * y2
|
||||
v0 := c.baseApi.Mul(r.Y, q.X)
|
||||
|
||||
// v1 = x2 * y1
|
||||
v1 := c.baseApi.Mul(r.X, q.Y)
|
||||
|
||||
// v2 = d * v0 * v1
|
||||
v2 := c.baseApi.Mul(c.d, v0, v1)
|
||||
|
||||
var px, py frontend.Variable
|
||||
|
||||
// x = (v0 + v1) / (1 + v2)
|
||||
px = c.baseApi.Add(v0, v1)
|
||||
px = c.baseApi.DivUnchecked(px, c.baseApi.Add(1, v2))
|
||||
|
||||
// y = (u + a * v0 - v1) / (1 - v2)
|
||||
py = c.baseApi.Mul(c.a, v0)
|
||||
py = c.baseApi.Sub(py, v1)
|
||||
py = c.baseApi.Add(py, u)
|
||||
py = c.baseApi.DivUnchecked(py, c.baseApi.Sub(1, v2))
|
||||
|
||||
return AffinePoint[T]{
|
||||
X: px.(emulated.Element[T]),
|
||||
Y: py.(emulated.Element[T]),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) Double(p AffinePoint[T]) AffinePoint[T] {
|
||||
u := c.baseApi.Mul(p.X, p.Y)
|
||||
v := c.baseApi.Mul(p.X, p.X)
|
||||
w := c.baseApi.Mul(p.Y, p.Y)
|
||||
|
||||
n1 := c.baseApi.Add(u, u)
|
||||
av := c.baseApi.Mul(v, c.a)
|
||||
n2 := c.baseApi.Sub(w, av)
|
||||
d1 := c.baseApi.Add(w, av)
|
||||
d2 := c.baseApi.Sub(2, d1)
|
||||
|
||||
px := c.baseApi.DivUnchecked(n1, d1)
|
||||
py := c.baseApi.DivUnchecked(n2, d2)
|
||||
|
||||
return AffinePoint[T]{
|
||||
X: px.(emulated.Element[T]),
|
||||
Y: py.(emulated.Element[T]),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) Select(b frontend.Variable, p, q AffinePoint[T]) AffinePoint[T] {
|
||||
x := c.baseApi.Select(b, p.X, q.X)
|
||||
y := c.baseApi.Select(b, p.Y, q.Y)
|
||||
return AffinePoint[T]{
|
||||
X: x.(emulated.Element[T]),
|
||||
Y: y.(emulated.Element[T]),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) ScalarMul(p AffinePoint[T], s emulated.Element[S]) AffinePoint[T] {
|
||||
return c.ScalarMulBinary(p, c.scalarApi.ToBinary(s))
|
||||
}
|
||||
|
||||
func (c *Curve[T, S]) ScalarMulBinary(p AffinePoint[T], sBits []frontend.Variable) AffinePoint[T] {
|
||||
res := AffinePoint[T]{
|
||||
X: emulated.NewElement[T](0),
|
||||
Y: emulated.NewElement[T](1),
|
||||
}
|
||||
acc := p
|
||||
|
||||
for i := 0; i < len(sBits); i++ {
|
||||
tmp := c.Add(res, acc)
|
||||
res = c.Select(sBits[i], tmp, res)
|
||||
acc = c.Double(acc)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
package edwards_curve
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/std/math/emulated"
|
||||
"github.com/consensys/gnark/test"
|
||||
// "github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
)
|
||||
|
||||
type OnCurveTest[T, S emulated.FieldParams] struct {
|
||||
P AffinePoint[T]
|
||||
}
|
||||
|
||||
func (c *OnCurveTest[T, S]) Define(api frontend.API) error {
|
||||
cr, err := New[T, S](api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cr.AssertIsOnCurve(c.P)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestGeneratorIsOnCurve(t *testing.T) {
|
||||
assert := test.NewAssert(t)
|
||||
circuit := OnCurveTest[Ed25519, Ed25519Scalars]{}
|
||||
witness := OnCurveTest[Ed25519, Ed25519Scalars]{
|
||||
P: AffinePoint[Ed25519]{
|
||||
X: emulated.NewElement[Ed25519](newBigInt("216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A")),
|
||||
Y: emulated.NewElement[Ed25519](newBigInt("6666666666666666666666666666666666666666666666666666666666666658")),
|
||||
},
|
||||
}
|
||||
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
// s1*x1 + s2*x2 = y
|
||||
type MulAddTest[T, S emulated.FieldParams] struct {
|
||||
X1, X2 AffinePoint[T]
|
||||
S1, S2 emulated.Element[S]
|
||||
Y AffinePoint[T]
|
||||
}
|
||||
|
||||
func (c *MulAddTest[T, S]) Define(api frontend.API) error {
|
||||
cr, err := New[T, S](api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
X1S1 := cr.ScalarMul(c.X1, c.S1)
|
||||
X2S2 := cr.ScalarMul(c.X2, c.S2)
|
||||
sum := cr.Add(X1S1, X2S2)
|
||||
cr.AssertIsEqual(sum, c.Y)
|
||||
cr.scalarApi.AssertIsEqual(
|
||||
cr.scalarApi.Add(c.S1, c.S2),
|
||||
emulated.NewElement[S](big.NewInt(1)),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestGeneratorGeneratesCurveOfCorrectOrder(t *testing.T) {
|
||||
assert := test.NewAssert(t)
|
||||
Gx, Gy := Ed25519{}.Generator()
|
||||
G := AffinePoint[Ed25519]{
|
||||
X: emulated.NewElement[Ed25519](Gx),
|
||||
Y: emulated.NewElement[Ed25519](Gy),
|
||||
}
|
||||
for i := 2; i <= 3; i++ {
|
||||
S1 := new(big.Int).Sub(rEd25519, big.NewInt(int64(i - 1)))
|
||||
S2 := big.NewInt(int64(i))
|
||||
circuit := MulAddTest[Ed25519, Ed25519Scalars]{}
|
||||
witness := MulAddTest[Ed25519, Ed25519Scalars]{
|
||||
X1: G,
|
||||
X2: G,
|
||||
S1: emulated.NewElement[Ed25519Scalars](S1),
|
||||
S2: emulated.NewElement[Ed25519Scalars](S2),
|
||||
Y: G,
|
||||
}
|
||||
err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
assert.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
var testCurve = ecc.BN254
|
||||
|
||||
// type NegTest[T, S emulated.FieldParams] struct {
|
||||
// P, Q AffinePoint[T]
|
||||
// }
|
||||
|
||||
// func (c *NegTest[T, S]) Define(api frontend.API) error {
|
||||
// cr, err := New[T, S](api)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// res := cr.Neg(c.P)
|
||||
// cr.AssertIsEqual(res, c.Q)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func TestNeg(t *testing.T) {
|
||||
// assert := test.NewAssert(t)
|
||||
// secpCurve := secp256k1.S256()
|
||||
// yn := new(big.Int).Sub(secpCurve.P, secpCurve.Gy)
|
||||
// circuit := NegTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{}
|
||||
// witness := NegTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{
|
||||
// P: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](secpCurve.Gx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](secpCurve.Gy),
|
||||
// },
|
||||
// Q: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](secpCurve.Gx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](yn),
|
||||
// },
|
||||
// }
|
||||
// err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
// assert.NoError(err)
|
||||
// }
|
||||
|
||||
// type AddTest[T, S emulated.FieldParams] struct {
|
||||
// P, Q, R AffinePoint[T]
|
||||
// }
|
||||
|
||||
// func (c *AddTest[T, S]) Define(api frontend.API) error {
|
||||
// cr, err := New[T, S](api)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// res := cr.Add(c.P, c.Q)
|
||||
// cr.AssertIsEqual(res, c.R)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func TestAdd(t *testing.T) {
|
||||
// assert := test.NewAssert(t)
|
||||
// secpCurve := secp256k1.S256()
|
||||
// xd, yd := secpCurve.Double(secpCurve.Gx, secpCurve.Gy)
|
||||
// xa, ya := secpCurve.Add(xd, yd, secpCurve.Gx, secpCurve.Gy)
|
||||
// circuit := AddTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{}
|
||||
// witness := AddTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{
|
||||
// P: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](secpCurve.Gx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](secpCurve.Gy),
|
||||
// },
|
||||
// Q: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](xd),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](yd),
|
||||
// },
|
||||
// R: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](xa),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](ya),
|
||||
// },
|
||||
// }
|
||||
// err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
// assert.NoError(err)
|
||||
// }
|
||||
|
||||
// type DoubleTest[T, S emulated.FieldParams] struct {
|
||||
// P, Q AffinePoint[T]
|
||||
// }
|
||||
|
||||
// func (c *DoubleTest[T, S]) Define(api frontend.API) error {
|
||||
// cr, err := New[T, S](api)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// res := cr.Double(c.P)
|
||||
// cr.AssertIsEqual(res, c.Q)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func TestDouble(t *testing.T) {
|
||||
// assert := test.NewAssert(t)
|
||||
// secpCurve := secp256k1.S256()
|
||||
// xd, yd := secpCurve.Double(secpCurve.Gx, secpCurve.Gy)
|
||||
// circuit := DoubleTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{}
|
||||
// witness := DoubleTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{
|
||||
// P: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](secpCurve.Gx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](secpCurve.Gy),
|
||||
// },
|
||||
// Q: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](xd),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](yd),
|
||||
// },
|
||||
// }
|
||||
// err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
// assert.NoError(err)
|
||||
// }
|
||||
|
||||
// type ScalarMulTest[T, S emulated.FieldParams] struct {
|
||||
// P, Q AffinePoint[T]
|
||||
// S emulated.Element[S]
|
||||
// }
|
||||
|
||||
// func (c *ScalarMulTest[T, S]) Define(api frontend.API) error {
|
||||
// cr, err := New[T, S](api)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// res := cr.ScalarMul(c.P, c.S)
|
||||
// cr.AssertIsEqual(res, c.Q)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func TestScalarMul(t *testing.T) {
|
||||
// assert := test.NewAssert(t)
|
||||
// secpCurve := secp256k1.S256()
|
||||
// s, ok := new(big.Int).SetString("44693544921776318736021182399461740191514036429448770306966433218654680512345", 10)
|
||||
// assert.True(ok)
|
||||
// sx, sy := secpCurve.ScalarMult(secpCurve.Gx, secpCurve.Gy, s.Bytes())
|
||||
|
||||
// circuit := ScalarMulTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{}
|
||||
// witness := ScalarMulTest[emulated.Secp256k1, emulated.Secp256k1Scalars]{
|
||||
// S: emulated.NewElement[emulated.Secp256k1Scalars](s),
|
||||
// P: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](secpCurve.Gx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](secpCurve.Gy),
|
||||
// },
|
||||
// Q: AffinePoint[emulated.Secp256k1]{
|
||||
// X: emulated.NewElement[emulated.Secp256k1](sx),
|
||||
// Y: emulated.NewElement[emulated.Secp256k1](sy),
|
||||
// },
|
||||
// }
|
||||
// err := test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
// assert.NoError(err)
|
||||
// // _, err = frontend.Compile(testCurve.ScalarField(), r1cs.NewBuilder, &circuit)
|
||||
// // assert.NoError(err)
|
||||
// }
|
||||
94
fibonacci.go
94
fibonacci.go
@ -1,94 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/plonky2_verifier"
|
||||
"gnark-ed25519/poseidon"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
)
|
||||
|
||||
type BenchmarkPlonky2VerifierCircuit struct {
|
||||
proofWithPis ProofWithPublicInputs
|
||||
|
||||
verifierChip *VerifierChip
|
||||
}
|
||||
|
||||
func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/fibonacci/proof_with_public_inputs.json")
|
||||
commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/fibonacci/common_circuit_data.json")
|
||||
verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/fibonacci/verifier_only_circuit_data.json")
|
||||
|
||||
fieldAPI := NewFieldAPI(api)
|
||||
qeAPI := NewQuadraticExtensionAPI(fieldAPI, commonCircuitData.DegreeBits)
|
||||
hashAPI := NewHashAPI(fieldAPI)
|
||||
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI)
|
||||
friChip := NewFriChip(api, fieldAPI, qeAPI, hashAPI, poseidonChip, &commonCircuitData.FriParams)
|
||||
plonkChip := NewPlonkChip(api, qeAPI, commonCircuitData)
|
||||
circuit.verifierChip = NewVerifierChip(api, fieldAPI, qeAPI, poseidonChip, plonkChip, friChip)
|
||||
|
||||
circuit.verifierChip.Verify(proofWithPis, verifierOnlyCircuitData, commonCircuitData)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileCircuit() frontend.CompiledConstraintSystem {
|
||||
circuit := BenchmarkPlonky2VerifierCircuit{}
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/fibonacci/proof_with_public_inputs.json")
|
||||
circuit.proofWithPis = proofWithPis
|
||||
|
||||
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
|
||||
if err != nil {
|
||||
fmt.Println("error in building circuit", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return r1cs
|
||||
}
|
||||
|
||||
func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/fibonacci/proof_with_public_inputs.json")
|
||||
|
||||
// Witness
|
||||
assignment := &BenchmarkPlonky2VerifierCircuit{
|
||||
proofWithPis: proofWithPis,
|
||||
}
|
||||
|
||||
fmt.Println("Generating witness", time.Now())
|
||||
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
publicWitness, _ := witness.Public()
|
||||
|
||||
fmt.Println("Running circuit setup", time.Now())
|
||||
pk, vk, err := groth16.Setup(r1cs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Creating proof", time.Now())
|
||||
proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Verifying proof", time.Now())
|
||||
err = groth16.Verify(proof, vk, publicWitness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return proof
|
||||
}
|
||||
|
||||
func main() {
|
||||
r1cs := compileCircuit()
|
||||
proof := createProof(r1cs)
|
||||
fmt.Println(proof.CurveID(), time.Now())
|
||||
}
|
||||
407
fri_benchmark.go
407
fri_benchmark.go
@ -1,407 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/plonky2_verifier"
|
||||
"gnark-ed25519/poseidon"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
)
|
||||
|
||||
type BenchmarkLargeDummyFriCircuit struct {
|
||||
zeta QuadraticExtension
|
||||
openings FriOpenings
|
||||
friChallenges FriChallenges
|
||||
initialMerkleCaps []MerkleCap
|
||||
friProof FriProof
|
||||
}
|
||||
|
||||
func (circuit *BenchmarkLargeDummyFriCircuit) Define(api frontend.API) error {
|
||||
commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
|
||||
|
||||
field := NewFieldAPI(api)
|
||||
qeAPI := NewQuadraticExtensionAPI(field, commonCircuitData.DegreeBits)
|
||||
poseidonChip := poseidon.NewPoseidonChip(api, field)
|
||||
friChip := NewFriChip(api, field, qeAPI, poseidonChip, &commonCircuitData.FriParams)
|
||||
|
||||
friChip.VerifyFriProof(
|
||||
commonCircuitData.GetFriInstance(qeAPI, circuit.zeta, commonCircuitData.DegreeBits),
|
||||
circuit.openings,
|
||||
&circuit.friChallenges,
|
||||
circuit.initialMerkleCaps,
|
||||
&circuit.friProof,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileCircuit() frontend.CompiledConstraintSystem {
|
||||
fmt.Println("compiling circuit", time.Now())
|
||||
circuit := BenchmarkLargeDummyFriCircuit{}
|
||||
|
||||
/*
|
||||
commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
|
||||
|
||||
circuit.zeta[0] = emulated.NewElement[EmulatedField](nil)
|
||||
circuit.zeta[1] = emulated.NewElement[EmulatedField](nil)
|
||||
|
||||
fmt.Println("circuit zeta allocated")
|
||||
|
||||
// Batch 0 has the following openings
|
||||
// Constants (config.num_constants + 1)
|
||||
// Sigmas (config.num_routed_wires)
|
||||
// Wires (config.num_wires)
|
||||
// Plonk_Z (config.num_challenges)
|
||||
// Partial Products (config.num_challenges * config.num_partial_products)
|
||||
// Quotient Polynomails (config.num_challenges * config.quotient_degree_factor)
|
||||
|
||||
// Batch 1 has the following openings
|
||||
// Plonk_Z_next (config.num_challenges)
|
||||
|
||||
circuit.openings.Batches = make([]FriOpeningBatch, 2)
|
||||
|
||||
batch1Size := commonCircuitData.NumConstants + 1 +
|
||||
commonCircuitData.Config.NumRoutedWires +
|
||||
commonCircuitData.Config.NumWires +
|
||||
commonCircuitData.Config.NumChallenges +
|
||||
(commonCircuitData.Config.NumChallenges * commonCircuitData.NumPartialProducts) +
|
||||
(commonCircuitData.Config.NumChallenges * commonCircuitData.QuotientDegreeFactor)
|
||||
|
||||
circuit.openings.Batches[0].Values = make([]QuadraticExtension, 0)
|
||||
for i := uint64(0); i < batch1Size; i++ {
|
||||
circuit.openings.Batches[0].Values = append(circuit.openings.Batches[0].Values, NewEmptyQuadraticExtension())
|
||||
}
|
||||
|
||||
batch2Size := commonCircuitData.Config.NumChallenges
|
||||
circuit.openings.Batches[1].Values = make([]QuadraticExtension, 0)
|
||||
for i := uint64(0); i < batch2Size; i++ {
|
||||
circuit.openings.Batches[1].Values = append(circuit.openings.Batches[1].Values, NewEmptyQuadraticExtension())
|
||||
}
|
||||
|
||||
fmt.Println("circuit openings allocated")
|
||||
|
||||
circuit.friChallenges.FriAlpha = NewEmptyQuadraticExtension()
|
||||
circuit.friChallenges.FriPowResponse = emulated.NewElement[EmulatedField](nil)
|
||||
circuit.friChallenges.FriBetas = make([]QuadraticExtension, 0)
|
||||
for i := 0; i < len(commonCircuitData.FriParams.ReductionArityBits); i++ {
|
||||
circuit.friChallenges.FriBetas = append(circuit.friChallenges.FriBetas, NewEmptyQuadraticExtension())
|
||||
}
|
||||
circuit.friChallenges.FriQueryIndicies = make([]F, 0)
|
||||
for i := uint64(0); i < commonCircuitData.FriParams.Config.NumQueryRounds; i++ {
|
||||
circuit.friChallenges.FriQueryIndicies = append(circuit.friChallenges.FriQueryIndicies, NewEmptyFieldElement())
|
||||
}
|
||||
|
||||
fmt.Println("circuit challenges allocated")
|
||||
|
||||
// initial merkle caps is the merkle cap for
|
||||
// the constant/sigmas, wires, partial products,
|
||||
// and quotient composite polynomial
|
||||
// The merkle cap size is 2**cap_height hashes
|
||||
numMerkleCaps := 4
|
||||
merkleCapSize := 1 << commonCircuitData.Config.FriConfig.CapHeight
|
||||
circuit.initialMerkleCaps = make([]MerkleCap, 0)
|
||||
for i := 0; i < numMerkleCaps; i++ {
|
||||
merkleCap := make([]Hash, 0)
|
||||
for j := 0; j < merkleCapSize; j++ {
|
||||
merkleCap = append(merkleCap, NewEmptyHash())
|
||||
}
|
||||
circuit.initialMerkleCaps = append(circuit.initialMerkleCaps, merkleCap)
|
||||
}
|
||||
|
||||
fmt.Println("circuit initialMerkleCaps allocated")
|
||||
|
||||
// CommitPhaseMerkleCap is number of reduction_arity_bits
|
||||
// finalPoly has 2^(degreeBits - sum(arity_bits)) coefficients
|
||||
numCommitPhaseMerkleCaps := len(commonCircuitData.FriParams.ReductionArityBits)
|
||||
for i := 0; i < numCommitPhaseMerkleCaps; i++ {
|
||||
circuit.friProof.CommitPhaseMerkleCaps = make([]MerkleCap, 0)
|
||||
merkleCap := make([]Hash, 0)
|
||||
for j := 0; j < merkleCapSize; j++ {
|
||||
merkleCap = append(merkleCap, NewEmptyHash())
|
||||
}
|
||||
circuit.friProof.CommitPhaseMerkleCaps = append(circuit.friProof.CommitPhaseMerkleCaps, merkleCap)
|
||||
}
|
||||
|
||||
fmt.Println("circuit friproof CommitPhaseMerkleCaps allocated")
|
||||
|
||||
friOracleInfo := commonCircuitData.FriOracles()
|
||||
circuit.friProof.QueryRoundProofs = make([]FriQueryRound, 0)
|
||||
for i := 0; i < int(commonCircuitData.FriParams.Config.NumQueryRounds); i++ {
|
||||
|
||||
evalsProof := make([]EvalProof, 0)
|
||||
// Allocation for the initial trees proof
|
||||
for j := 0; j < len(friOracleInfo); j++ {
|
||||
leafSize := friOracleInfo[0].NumPolys
|
||||
merkleProofLen := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits - commonCircuitData.Config.FriConfig.CapHeight
|
||||
|
||||
evalElements := make([]F, 0)
|
||||
for k := uint64(0); k < leafSize; k++ {
|
||||
evalElements = append(evalElements, NewEmptyFieldElement())
|
||||
}
|
||||
|
||||
merkleProofSiblings := make([]Hash, 0)
|
||||
for k := uint64(0); k < merkleProofLen; k++ {
|
||||
merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash())
|
||||
}
|
||||
|
||||
evalsProof = append(
|
||||
evalsProof,
|
||||
EvalProof{
|
||||
Elements: evalElements,
|
||||
MerkleProof: MerkleProof{merkleProofSiblings},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Allocation for the steps
|
||||
steps := make([]FriQueryStep, 0)
|
||||
codewordLenBits := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits
|
||||
for j := 0; j < len(commonCircuitData.FriParams.ReductionArityBits); j++ {
|
||||
arityBits := commonCircuitData.FriParams.ReductionArityBits[j]
|
||||
leafSize := 1 << int(arityBits)
|
||||
codewordLenBits -= arityBits
|
||||
merkleProofLen := codewordLenBits - commonCircuitData.Config.FriConfig.CapHeight
|
||||
|
||||
evalQEs := make([]QuadraticExtension, 0)
|
||||
for k := 0; k < leafSize; k++ {
|
||||
evalQEs = append(evalQEs, NewEmptyQuadraticExtension())
|
||||
}
|
||||
|
||||
merkleProofSiblings := make([]Hash, 0)
|
||||
for k := uint64(0); k < merkleProofLen; k++ {
|
||||
merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash())
|
||||
}
|
||||
|
||||
steps = append(
|
||||
steps,
|
||||
FriQueryStep{
|
||||
Evals: evalQEs,
|
||||
MerkleProof: MerkleProof{merkleProofSiblings},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
circuit.friProof.QueryRoundProofs = append(
|
||||
circuit.friProof.QueryRoundProofs,
|
||||
FriQueryRound{
|
||||
InitialTreesProof: FriInitialTreeProof{evalsProof},
|
||||
Steps: steps,
|
||||
},
|
||||
)
|
||||
|
||||
fmt.Println("circuit friproof QueryRoundProofs allocated for round", i)
|
||||
}
|
||||
|
||||
// Final poly allocation
|
||||
finalPolyLenBit := commonCircuitData.DegreeBits
|
||||
for _, arityBit := range commonCircuitData.FriParams.ReductionArityBits {
|
||||
finalPolyLenBit -= arityBit
|
||||
}
|
||||
|
||||
circuit.friProof.FinalPoly.Coeffs = make([]QuadraticExtension, 0)
|
||||
for i := 0; i < (1 << finalPolyLenBit); i++ {
|
||||
circuit.friProof.FinalPoly.Coeffs = append(circuit.friProof.FinalPoly.Coeffs, NewEmptyQuadraticExtension())
|
||||
}
|
||||
|
||||
fmt.Println("circuit friproof FinalPoly allocated")
|
||||
|
||||
// PowWitness allocation
|
||||
circuit.friProof.PowWitness = NewEmptyFieldElement()
|
||||
fmt.Println("Partial witness allocation done")
|
||||
*/
|
||||
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json")
|
||||
|
||||
zeta := QuadraticExtension{
|
||||
NewFieldElementFromString("17377750363769967882"),
|
||||
NewFieldElementFromString("11921191651424768462"),
|
||||
}
|
||||
friChallenges := FriChallenges{
|
||||
FriAlpha: QuadraticExtension{
|
||||
NewFieldElementFromString("16721004555774385479"),
|
||||
NewFieldElementFromString("10688151135543754663"),
|
||||
},
|
||||
FriBetas: []QuadraticExtension{
|
||||
{
|
||||
NewFieldElementFromString("3312441922957827805"),
|
||||
NewFieldElementFromString("15128092514958289671"),
|
||||
},
|
||||
{
|
||||
NewFieldElementFromString("13630530769060141802"),
|
||||
NewFieldElementFromString("14559883974933163008"),
|
||||
},
|
||||
{
|
||||
NewFieldElementFromString("16146508250083930687"),
|
||||
NewFieldElementFromString("5176346568444408396"),
|
||||
},
|
||||
},
|
||||
FriPowResponse: NewFieldElement(4389),
|
||||
FriQueryIndicies: []F{
|
||||
NewFieldElementFromString("16334967868590615051"),
|
||||
NewFieldElementFromString("2911473540496037915"),
|
||||
NewFieldElementFromString("14887216056886344225"),
|
||||
NewFieldElementFromString("7808811227805914295"),
|
||||
NewFieldElementFromString("2018594961417375749"),
|
||||
NewFieldElementFromString("3733368398777208435"),
|
||||
NewFieldElementFromString("2623035669037055104"),
|
||||
NewFieldElementFromString("299243030573481514"),
|
||||
NewFieldElementFromString("7189789717962704433"),
|
||||
NewFieldElementFromString("14566344026886816268"),
|
||||
NewFieldElementFromString("12555390069003437453"),
|
||||
NewFieldElementFromString("17225508403199418233"),
|
||||
NewFieldElementFromString("5088797913879903292"),
|
||||
NewFieldElementFromString("9715691392773433023"),
|
||||
NewFieldElementFromString("7565836764713256165"),
|
||||
NewFieldElementFromString("1500143546029322929"),
|
||||
NewFieldElementFromString("1245802417104422080"),
|
||||
NewFieldElementFromString("6831959786661245110"),
|
||||
NewFieldElementFromString("17271054758535453780"),
|
||||
NewFieldElementFromString("6225460404576395409"),
|
||||
NewFieldElementFromString("15932661092896277351"),
|
||||
NewFieldElementFromString("12452534049198240575"),
|
||||
NewFieldElementFromString("4225199666055520177"),
|
||||
NewFieldElementFromString("13235091290587791090"),
|
||||
NewFieldElementFromString("2562357622728700774"),
|
||||
NewFieldElementFromString("17676678042980201498"),
|
||||
NewFieldElementFromString("5837067135702409874"),
|
||||
NewFieldElementFromString("11238419549114325157"),
|
||||
},
|
||||
}
|
||||
|
||||
initialMerkleCaps := []MerkleCap{
|
||||
verifierOnlyCircuitData.ConstantSigmasCap,
|
||||
proofWithPis.Proof.WiresCap,
|
||||
proofWithPis.Proof.PlonkZsPartialProductsCap,
|
||||
proofWithPis.Proof.QuotientPolysCap,
|
||||
}
|
||||
|
||||
circuit.zeta = zeta
|
||||
circuit.openings = proofWithPis.Proof.Openings.ToFriOpenings()
|
||||
circuit.friChallenges = friChallenges
|
||||
circuit.initialMerkleCaps = initialMerkleCaps
|
||||
circuit.friProof = proofWithPis.Proof.OpeningProof
|
||||
|
||||
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
|
||||
if err != nil {
|
||||
fmt.Println("error in building circuit", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return r1cs
|
||||
}
|
||||
|
||||
func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json")
|
||||
|
||||
zeta := QuadraticExtension{
|
||||
NewFieldElementFromString("17377750363769967882"),
|
||||
NewFieldElementFromString("11921191651424768462"),
|
||||
}
|
||||
friChallenges := FriChallenges{
|
||||
FriAlpha: QuadraticExtension{
|
||||
NewFieldElementFromString("16721004555774385479"),
|
||||
NewFieldElementFromString("10688151135543754663"),
|
||||
},
|
||||
FriBetas: []QuadraticExtension{
|
||||
{
|
||||
NewFieldElementFromString("3312441922957827805"),
|
||||
NewFieldElementFromString("15128092514958289671"),
|
||||
},
|
||||
{
|
||||
NewFieldElementFromString("13630530769060141802"),
|
||||
NewFieldElementFromString("14559883974933163008"),
|
||||
},
|
||||
{
|
||||
NewFieldElementFromString("16146508250083930687"),
|
||||
NewFieldElementFromString("5176346568444408396"),
|
||||
},
|
||||
},
|
||||
FriPowResponse: NewFieldElement(4389),
|
||||
FriQueryIndicies: []F{
|
||||
NewFieldElementFromString("16334967868590615051"),
|
||||
NewFieldElementFromString("2911473540496037915"),
|
||||
NewFieldElementFromString("14887216056886344225"),
|
||||
NewFieldElementFromString("7808811227805914295"),
|
||||
NewFieldElementFromString("2018594961417375749"),
|
||||
NewFieldElementFromString("3733368398777208435"),
|
||||
NewFieldElementFromString("2623035669037055104"),
|
||||
NewFieldElementFromString("299243030573481514"),
|
||||
NewFieldElementFromString("7189789717962704433"),
|
||||
NewFieldElementFromString("14566344026886816268"),
|
||||
NewFieldElementFromString("12555390069003437453"),
|
||||
NewFieldElementFromString("17225508403199418233"),
|
||||
NewFieldElementFromString("5088797913879903292"),
|
||||
NewFieldElementFromString("9715691392773433023"),
|
||||
NewFieldElementFromString("7565836764713256165"),
|
||||
NewFieldElementFromString("1500143546029322929"),
|
||||
NewFieldElementFromString("1245802417104422080"),
|
||||
NewFieldElementFromString("6831959786661245110"),
|
||||
NewFieldElementFromString("17271054758535453780"),
|
||||
NewFieldElementFromString("6225460404576395409"),
|
||||
NewFieldElementFromString("15932661092896277351"),
|
||||
NewFieldElementFromString("12452534049198240575"),
|
||||
NewFieldElementFromString("4225199666055520177"),
|
||||
NewFieldElementFromString("13235091290587791090"),
|
||||
NewFieldElementFromString("2562357622728700774"),
|
||||
NewFieldElementFromString("17676678042980201498"),
|
||||
NewFieldElementFromString("5837067135702409874"),
|
||||
NewFieldElementFromString("11238419549114325157"),
|
||||
},
|
||||
}
|
||||
|
||||
initialMerkleCaps := []MerkleCap{
|
||||
verifierOnlyCircuitData.ConstantSigmasCap,
|
||||
proofWithPis.Proof.WiresCap,
|
||||
proofWithPis.Proof.PlonkZsPartialProductsCap,
|
||||
proofWithPis.Proof.QuotientPolysCap,
|
||||
}
|
||||
|
||||
// Witness
|
||||
assignment := &BenchmarkLargeDummyFriCircuit{
|
||||
zeta: zeta,
|
||||
openings: proofWithPis.Proof.Openings.ToFriOpenings(),
|
||||
friChallenges: friChallenges,
|
||||
initialMerkleCaps: initialMerkleCaps,
|
||||
friProof: proofWithPis.Proof.OpeningProof,
|
||||
}
|
||||
|
||||
fmt.Println("Generating witness", time.Now())
|
||||
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
publicWitness, _ := witness.Public()
|
||||
pk, vk, err := groth16.Setup(r1cs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Creating proof", time.Now())
|
||||
proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Verifying proof", time.Now())
|
||||
err = groth16.Verify(proof, vk, publicWitness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return proof
|
||||
}
|
||||
|
||||
func main() {
|
||||
r1cs := compileCircuit()
|
||||
fi, _ := os.Open("dummy_fri.r1cs")
|
||||
r1cs.WriteTo(fi)
|
||||
proof := createProof(r1cs)
|
||||
fmt.Println(proof.CurveID(), time.Now())
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/plonky2_verifier"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
)
|
||||
|
||||
type BenchmarkPlonkCircuit struct {
|
||||
proofChallenges ProofChallenges
|
||||
openings OpeningSet
|
||||
}
|
||||
|
||||
func (circuit *BenchmarkPlonkCircuit) Define(api frontend.API) error {
|
||||
commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
|
||||
|
||||
field := NewFieldAPI(api)
|
||||
qeAPI := NewQuadraticExtensionAPI(field, commonCircuitData.DegreeBits)
|
||||
|
||||
plonkChip := NewPlonkChip(api, qeAPI, commonCircuitData)
|
||||
|
||||
plonkChip.Verify(circuit.proofChallenges, circuit.openings)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileCircuit() frontend.CompiledConstraintSystem {
|
||||
fmt.Println("compiling circuit", time.Now())
|
||||
circuit := BenchmarkPlonkCircuit{}
|
||||
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
|
||||
// Challenge associated with the data from "/.data/dummy_2^14_gates/*"
|
||||
proofChallenges := ProofChallenges{
|
||||
PlonkBetas: []F{
|
||||
NewFieldElementFromString("4678728155650926271"),
|
||||
NewFieldElementFromString("13611962404289024887"),
|
||||
},
|
||||
PlonkGammas: []F{
|
||||
NewFieldElementFromString("13237663823305715949"),
|
||||
NewFieldElementFromString("15389314098328235145"),
|
||||
},
|
||||
PlonkAlphas: []F{
|
||||
NewFieldElementFromString("14505919539124304197"),
|
||||
NewFieldElementFromString("1695455639263736117"),
|
||||
},
|
||||
PlonkZeta: QuadraticExtension{
|
||||
NewFieldElementFromString("14887793628029982930"),
|
||||
NewFieldElementFromString("1136137158284059037"),
|
||||
},
|
||||
}
|
||||
|
||||
circuit.proofChallenges = proofChallenges
|
||||
circuit.openings = proofWithPis.Proof.Openings
|
||||
|
||||
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
|
||||
if err != nil {
|
||||
fmt.Println("error in building circuit", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return r1cs
|
||||
}
|
||||
|
||||
func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
|
||||
// Challenge associated with the data from "/.data/dummy_2^14_gates/*"
|
||||
proofChallenges := ProofChallenges{
|
||||
PlonkBetas: []F{
|
||||
NewFieldElementFromString("4678728155650926271"),
|
||||
NewFieldElementFromString("13611962404289024887"),
|
||||
},
|
||||
PlonkGammas: []F{
|
||||
NewFieldElementFromString("13237663823305715949"),
|
||||
NewFieldElementFromString("15389314098328235145"),
|
||||
},
|
||||
PlonkAlphas: []F{
|
||||
NewFieldElementFromString("14505919539124304197"),
|
||||
NewFieldElementFromString("1695455639263736117"),
|
||||
},
|
||||
PlonkZeta: QuadraticExtension{
|
||||
NewFieldElementFromString("14887793628029982930"),
|
||||
NewFieldElementFromString("1136137158284059037"),
|
||||
},
|
||||
}
|
||||
|
||||
// Witness
|
||||
assignment := &BenchmarkPlonkCircuit{
|
||||
proofChallenges: proofChallenges,
|
||||
openings: proofWithPis.Proof.Openings,
|
||||
}
|
||||
|
||||
fmt.Println("Generating witness", time.Now())
|
||||
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
publicWitness, _ := witness.Public()
|
||||
pk, vk, err := groth16.Setup(r1cs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Creating proof", time.Now())
|
||||
proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Verifying proof", time.Now())
|
||||
err = groth16.Verify(proof, vk, publicWitness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return proof
|
||||
}
|
||||
|
||||
func main() {
|
||||
r1cs := compileCircuit()
|
||||
fi, _ := os.Open("dummy_fri.r1cs")
|
||||
r1cs.WriteTo(fi)
|
||||
proof := createProof(r1cs)
|
||||
fmt.Println(proof.CurveID(), time.Now())
|
||||
}
|
||||
@ -2,8 +2,8 @@ package plonky2_verifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/poseidon"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/poseidon"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
"gnark-ed25519/field"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/poseidon"
|
||||
"gnark-ed25519/utils"
|
||||
"gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/poseidon"
|
||||
"gnark-plonky2-verifier/utils"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -2,8 +2,8 @@ package plonky2_verifier
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/utils"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/utils"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -2,9 +2,9 @@ package plonky2_verifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gnark-ed25519/field"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/poseidon"
|
||||
"gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/poseidon"
|
||||
"math"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/poseidon"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/poseidon"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
"gnark-ed25519/field"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
)
|
||||
|
||||
type FriOpeningBatch struct {
|
||||
|
||||
@ -2,7 +2,7 @@ package plonky2_verifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -2,7 +2,7 @@ package plonky2_verifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"math/bits"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
"gnark-ed25519/field"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
)
|
||||
|
||||
type MerkleCap = []Hash
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/poseidon"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/poseidon"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package plonky2_verifier
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/poseidon"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/poseidon"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-ed25519/plonky2_verifier"
|
||||
"gnark-ed25519/poseidon"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/frontend/cs/r1cs"
|
||||
)
|
||||
|
||||
type BenchmarkPlonky2VerifierCircuit struct {
|
||||
proofWithPis ProofWithPublicInputs
|
||||
|
||||
verifierChip *VerifierChip
|
||||
}
|
||||
|
||||
func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
|
||||
verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json")
|
||||
|
||||
fieldAPI := NewFieldAPI(api)
|
||||
qeAPI := NewQuadraticExtensionAPI(fieldAPI, commonCircuitData.DegreeBits)
|
||||
hashAPI := NewHashAPI(fieldAPI)
|
||||
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI)
|
||||
friChip := NewFriChip(api, fieldAPI, qeAPI, hashAPI, poseidonChip, &commonCircuitData.FriParams)
|
||||
plonkChip := NewPlonkChip(api, qeAPI, commonCircuitData)
|
||||
circuit.verifierChip = NewVerifierChip(api, fieldAPI, qeAPI, poseidonChip, plonkChip, friChip)
|
||||
|
||||
circuit.verifierChip.Verify(proofWithPis, verifierOnlyCircuitData, commonCircuitData)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileCircuit() frontend.CompiledConstraintSystem {
|
||||
circuit := BenchmarkPlonky2VerifierCircuit{}
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
circuit.proofWithPis = proofWithPis
|
||||
|
||||
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
|
||||
if err != nil {
|
||||
fmt.Println("error in building circuit", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return r1cs
|
||||
}
|
||||
|
||||
func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof {
|
||||
proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
|
||||
|
||||
// Witness
|
||||
assignment := &BenchmarkPlonky2VerifierCircuit{
|
||||
proofWithPis: proofWithPis,
|
||||
}
|
||||
|
||||
fmt.Println("Generating witness", time.Now())
|
||||
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
||||
publicWitness, _ := witness.Public()
|
||||
|
||||
fmt.Println("Running circuit setup", time.Now())
|
||||
pk, vk, err := groth16.Setup(r1cs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Creating proof", time.Now())
|
||||
proof, err := groth16.Prove(r1cs, pk, witness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Verifying proof", time.Now())
|
||||
err = groth16.Verify(proof, vk, publicWitness)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return proof
|
||||
}
|
||||
|
||||
func main() {
|
||||
r1cs := compileCircuit()
|
||||
proof := createProof(r1cs)
|
||||
fmt.Println(proof.CurveID(), time.Now())
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package poseidon
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package poseidon
|
||||
|
||||
import (
|
||||
"gnark-ed25519/field"
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/utils"
|
||||
"gnark-plonky2-verifier/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/utils"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark/backend/groth16"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package poseidon
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
"gnark-ed25519/utils"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"gnark-plonky2-verifier/utils"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
|
||||
293
sha512/sha512.go
293
sha512/sha512.go
@ -1,293 +0,0 @@
|
||||
package sha512
|
||||
|
||||
/* Based on https://gist.github.com/illia-v/7883be942da5d416521375004cecb68f */
|
||||
|
||||
import (
|
||||
"github.com/consensys/gnark/frontend"
|
||||
)
|
||||
|
||||
func Sha512(api frontend.API, in []frontend.Variable) [512]frontend.Variable {
|
||||
_not := func(x [64]frontend.Variable) [64]frontend.Variable {
|
||||
return not(api, x)
|
||||
}
|
||||
_and := func(xs ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
return and(api, xs...)
|
||||
}
|
||||
_add := func(xs ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
return add(api, xs...)
|
||||
}
|
||||
_xor := func(xs ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
return xor(api, xs...)
|
||||
}
|
||||
zip_add := func(a, b Array8_64) Array8_64 {
|
||||
a0, a1, a2, a3, a4, a5, a6, a7 := unpack8(a)
|
||||
b0, b1, b2, b3, b4, b5, b6, b7 := unpack8(b)
|
||||
return Array8_64{
|
||||
_add(a0, b0),
|
||||
_add(a1, b1),
|
||||
_add(a2, b2),
|
||||
_add(a3, b3),
|
||||
_add(a4, b4),
|
||||
_add(a5, b5),
|
||||
_add(a6, b6),
|
||||
_add(a7, b7),
|
||||
}
|
||||
}
|
||||
initial_hash := []uint64{
|
||||
0x6a09e667f3bcc908,
|
||||
0xbb67ae8584caa73b,
|
||||
0x3c6ef372fe94f82b,
|
||||
0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1,
|
||||
0x9b05688c2b3e6c1f,
|
||||
0x1f83d9abfb41bd6b,
|
||||
0x5be0cd19137e2179,
|
||||
}
|
||||
round_constants := []uint64{
|
||||
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
|
||||
0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
|
||||
0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
|
||||
0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
|
||||
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
|
||||
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
|
||||
0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
|
||||
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
|
||||
0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
|
||||
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
|
||||
0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
|
||||
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
|
||||
0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
|
||||
0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
|
||||
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
|
||||
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
|
||||
0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
|
||||
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
|
||||
0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
|
||||
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
|
||||
0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
|
||||
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
|
||||
0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
|
||||
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
|
||||
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
|
||||
0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
|
||||
}
|
||||
for _, v := range in {
|
||||
api.AssertIsBoolean(v)
|
||||
}
|
||||
mdi := divChecked(len(in), 8) % 128
|
||||
var padding_len int
|
||||
if mdi < 112 {
|
||||
padding_len = 119 - mdi
|
||||
} else {
|
||||
padding_len = 247 - mdi
|
||||
}
|
||||
message_length_bits := uint64ToBits(uint64(len(in)))
|
||||
in = append(in, 1)
|
||||
for i := 0; i < 7; i++ {
|
||||
in = append(in, 0)
|
||||
}
|
||||
for i := 0; i < padding_len*8; i++ {
|
||||
in = append(in, 0)
|
||||
}
|
||||
for i := 0; i < 64; i++ {
|
||||
in = append(in, message_length_bits[i])
|
||||
}
|
||||
|
||||
sha512_hash := Array8_64{
|
||||
uint64ToBits(initial_hash[0]),
|
||||
uint64ToBits(initial_hash[1]),
|
||||
uint64ToBits(initial_hash[2]),
|
||||
uint64ToBits(initial_hash[3]),
|
||||
uint64ToBits(initial_hash[4]),
|
||||
uint64ToBits(initial_hash[5]),
|
||||
uint64ToBits(initial_hash[6]),
|
||||
uint64ToBits(initial_hash[7]),
|
||||
}
|
||||
for chunk_start := 0; chunk_start < divChecked(len(in), 8); chunk_start += 128 {
|
||||
chunk := in[chunk_start*8 : (chunk_start+128)*8]
|
||||
if len(chunk) != 1024 {
|
||||
panic("bad length")
|
||||
}
|
||||
u := make([]frontend.Variable, 80*64)
|
||||
for i, _ := range u {
|
||||
u[i] = 0
|
||||
}
|
||||
copy(u, chunk)
|
||||
|
||||
w := reshape(u)
|
||||
|
||||
for i := 16; i < 80; i++ {
|
||||
s0 := _xor(
|
||||
_right_rotate(w[i-15], 1),
|
||||
_right_rotate(w[i-15], 8),
|
||||
_shr(w[i-15], 7),
|
||||
)
|
||||
s1 := _xor(
|
||||
_right_rotate(w[i-2], 19),
|
||||
_right_rotate(w[i-2], 61),
|
||||
_shr(w[i-2], 6),
|
||||
)
|
||||
w[i] = _add(w[i-16], s0, w[i-7], s1)
|
||||
}
|
||||
a, b, c, d, e, f, g, h := unpack8(sha512_hash)
|
||||
for i := 0; i < 80; i++ {
|
||||
sum1 := _xor(
|
||||
_right_rotate(e, 14),
|
||||
_right_rotate(e, 18),
|
||||
_right_rotate(e, 41),
|
||||
)
|
||||
ch := _xor(_and(e, f), _and(_not(e), g))
|
||||
temp1 := _add(h, sum1, ch, uint64ToBits(round_constants[i]), w[i])
|
||||
sum0 := _xor(
|
||||
_right_rotate(a, 28),
|
||||
_right_rotate(a, 34),
|
||||
_right_rotate(a, 39),
|
||||
)
|
||||
maj := _xor(_and(a, b), _and(a, c), _and(b, c))
|
||||
temp2 := _add(sum0, maj)
|
||||
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = _add(d, temp1)
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = _add(temp1, temp2)
|
||||
}
|
||||
sha512_hash = zip_add(sha512_hash, Array8_64{a, b, c, d, e, f, g, h})
|
||||
}
|
||||
return flatten8(sha512_hash)
|
||||
}
|
||||
|
||||
func _right_rotate(n [64]frontend.Variable, bits int) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for i := 0; i < len(n); i++ {
|
||||
result[(i+bits)%len(n)] = n[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func reshape(u []frontend.Variable) [][64]frontend.Variable {
|
||||
l := divChecked(len(u), 64)
|
||||
result := make([][64]frontend.Variable, l)
|
||||
for i := 0; i < l; i++ {
|
||||
var arr [64]frontend.Variable
|
||||
for k := 0; k < 64; k++ {
|
||||
arr[k] = u[i*64+k]
|
||||
}
|
||||
result[i] = arr
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type Array8_64 [8][64]frontend.Variable
|
||||
|
||||
func unpack8(x Array8_64) ([64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable, [64]frontend.Variable) {
|
||||
return x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]
|
||||
}
|
||||
|
||||
func flatten8(x Array8_64) [512]frontend.Variable {
|
||||
var result [512]frontend.Variable
|
||||
k := 0
|
||||
for i := 0; i < 8; i++ {
|
||||
for j := 0; j < 64; j++ {
|
||||
result[k] = x[i][j]
|
||||
k++
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func uint64ToBits(value uint64) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for k := 0; k < 64; k++ {
|
||||
if (value & (1 << (63 - k))) != 0 {
|
||||
result[k] = 1
|
||||
} else {
|
||||
result[k] = 0
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func xor(api frontend.API, args ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
if len(args) == 1 {
|
||||
return args[0]
|
||||
} else {
|
||||
return xor2(api, args[0], xor(api, args[1:]...))
|
||||
}
|
||||
}
|
||||
func add(api frontend.API, args ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
if len(args) == 1 {
|
||||
return args[0]
|
||||
} else {
|
||||
return add2(api, args[0], add(api, args[1:]...))
|
||||
}
|
||||
}
|
||||
func and(api frontend.API, args ...[64]frontend.Variable) [64]frontend.Variable {
|
||||
if len(args) == 1 {
|
||||
return args[0]
|
||||
} else {
|
||||
return and2(api, args[0], and(api, args[1:]...))
|
||||
}
|
||||
}
|
||||
|
||||
func xor2(api frontend.API, a, b [64]frontend.Variable) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for i := 0; i < 64; i++ {
|
||||
result[i] = api.Xor(a[i], b[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func and2(api frontend.API, a, b [64]frontend.Variable) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for i := 0; i < 64; i++ {
|
||||
result[i] = api.And(a[i], b[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func add2(api frontend.API, a, b [64]frontend.Variable) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
var carry frontend.Variable = 0
|
||||
for i := 63; i >= 0; i-- {
|
||||
sum := api.Add(a[i], b[i], carry)
|
||||
sumBin := api.ToBinary(sum, 2)
|
||||
if len(sumBin) != 2 {
|
||||
panic("bad length")
|
||||
}
|
||||
result[i] = sumBin[0]
|
||||
carry = sumBin[1]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func _shr(n [64]frontend.Variable, bits int) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for i := 0; i < 64; i++ {
|
||||
if i < bits {
|
||||
result[i] = 0
|
||||
} else {
|
||||
result[i] = n[i-bits]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func not(api frontend.API, n [64]frontend.Variable) [64]frontend.Variable {
|
||||
var result [64]frontend.Variable
|
||||
for i := 0; i < 64; i++ {
|
||||
result[i] = api.Sub(1, n[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func divChecked(a, b int) int {
|
||||
if a%b != 0 {
|
||||
panic("divChecked: does not divide evenly")
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc"
|
||||
"github.com/consensys/gnark/frontend"
|
||||
"github.com/consensys/gnark/test"
|
||||
)
|
||||
|
||||
type TestSha512Circuit struct {
|
||||
in []frontend.Variable `gnark:"in"`
|
||||
out []frontend.Variable `gnark:"out"`
|
||||
}
|
||||
|
||||
func (circuit *TestSha512Circuit) Define(api frontend.API) error {
|
||||
res := Sha512(api, circuit.in)
|
||||
if len(res) != 512 {
|
||||
panic("bad length")
|
||||
}
|
||||
for i := 0; i < 512; i++ {
|
||||
api.AssertIsEqual(res[i], circuit.out[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var testCurve = ecc.BN254
|
||||
|
||||
func TestSha512Witness(t *testing.T) {
|
||||
assert := test.NewAssert(t)
|
||||
|
||||
testCase := func(in []byte, output string) {
|
||||
out, err := hex.DecodeString(output)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(out) != 512/8 {
|
||||
panic("bad output length")
|
||||
}
|
||||
|
||||
circuit := TestSha512Circuit{
|
||||
in: toBits(in),
|
||||
out: toBits(out),
|
||||
}
|
||||
witness := TestSha512Circuit{
|
||||
in: toBits(in),
|
||||
out: toBits(out),
|
||||
}
|
||||
err = test.IsSolved(&circuit, &witness, testCurve.ScalarField())
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
testCase([]byte(""), "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
|
||||
testCase([]byte("Succinct Labs"), "503ace098aa03f6feec1b5df0a38aee923f744a775508bc81f2b94ad139be297c2e8cd8c44af527b5d3f017a7fc929892c896604047e52e3f518924f52bff0dc")
|
||||
testCase(decode("35c323757c20640a294345c89c0bfcebe3d554fdb0c7b7a0bdb72222c531b1ecf7ec1c43f4de9d49556de87b86b26a98942cb078486fdb44de38b80864c3973153756363696e6374204c616273"), "4388243c4452274402673de881b2f942ff5730fd2c7d8ddb94c3e3d789fb3754380cba8faa40554d9506a0730a681e88ab348a04bc5c41d18926f140b59aed39")
|
||||
}
|
||||
|
||||
func toBits(arr []byte) []frontend.Variable {
|
||||
result := make([]frontend.Variable, len(arr)*8)
|
||||
for i, v := range arr {
|
||||
for j := 0; j < 8; j++ {
|
||||
if (v & (1 << (7 - j))) != 0 {
|
||||
result[i*8+j] = 1
|
||||
} else {
|
||||
result[i*8+j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func decode(s string) []byte {
|
||||
result, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
. "gnark-ed25519/field"
|
||||
. "gnark-plonky2-verifier/field"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark/frontend"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user