From e4fac3c39ffc5077dab16ac6edfbdfd431292b2f Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Wed, 18 Sep 2024 14:49:42 +0200 Subject: [PATCH 1/6] sparatan initial --- main.go | 144 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 43 deletions(-) diff --git a/main.go b/main.go index 2c7dc2b..9232c3b 100644 --- a/main.go +++ b/main.go @@ -1,62 +1,120 @@ package main -import( - "github.com/vocdoni/gnark-crypto-primitives/poseidon" - "github.com/consensys/gnark/frontend/cs/r1cs" - "github.com/consensys/gnark/backend/groth16" +import ( + "math/big" + "math/rand" + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "tutorial/sumcheck-verifier-circuit/polynomials" - // "github.com/kr/pretty" - "math/big" + "github.com/consensys/gnark/frontend/cs/r1cs" ) type Circuit struct { - Seed frontend.Variable `gnark:"Seed"` - C1 frontend.Variable `gnark:"C1"` - R1 frontend.Variable `gnark:"R1"` - R2 frontend.Variable `gnark:"R2"` - G_Coeffs [4]frontend.Variable `gnark:"G Coefficients"` - G1_Coeffs [2]frontend.Variable `gnark:"G1 Coefficients"` - G2_Coeffs [2]frontend.Variable `gnark:"G2 Coefficients"` + // Alleged computed sum of all the evaluations + ExpectedSum frontend.Variable `gnark:"ExpectedSum"` + ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` + ChallengeVector []frontend.Variable `gnark:"ChallengeVector"` + // Array of elements representing the values of p0, p1 in each of the rounds + GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` +} + +const NUMBER_OF_COEFFS_IN_LINEAR = 2 + +var ONE_HALF_CONSTANT *big.Int + +func Init() { + var success bool + ONE_HALF_CONSTANT, success = new(big.Int).SetString("10944121435919637611123202872628637544274182200208017171849102093287904247809", 10) + if !success { + println("Error: Failed to set big.Int value") + } } -func (circuit *Circuit) Define (api frontend.API) error { - g1_0 := polynomials.CircUniPoly(circuit.G1_Coeffs[:], 0, api) - g1_1 := polynomials.CircUniPoly(circuit.G1_Coeffs[:], 1, api) - api.AssertIsEqual(circuit.C1, api.Add(g1_0, g1_1)) - api.AssertIsEqual(circuit.R1, poseidon.Hash(api, circuit.Seed)) - g2_0 := polynomials.CircUniPoly(circuit.G2_Coeffs[:], 0, api) - g2_1 := polynomials.CircUniPoly(circuit.G2_Coeffs[:], 1, api) - g1_r1 := polynomials.CircUniPoly(circuit.G1_Coeffs[:], circuit.R1, api) - api.AssertIsEqual(api.Add(g2_0, g2_1), g1_r1) - api.AssertIsEqual(poseidon.Hash(api, circuit.R1), circuit.R2) - g2_r2 := polynomials.CircUniPoly(circuit.G2_Coeffs[:], circuit.R2, api) - g_eval := polynomials.CircMultPoly(circuit.G_Coeffs[:], []frontend.Variable{circuit.R1, circuit.R2}, api) - api.AssertIsEqual(g2_r2, g_eval) +func (circuit *Circuit) Define(api frontend.API) error { + // var manager = hashmanager.NewHashManager(api) + api.AssertIsEqual(circuit.ExpectedSum, api.Add(circuit.GPolynomials[0][0], api.Add(circuit.GPolynomials[0][0], circuit.GPolynomials[0][1]))) + g_length := len(circuit.GPolynomials) + api.AssertIsEqual(g_length, len(circuit.ChallengeVector)) + e := circuit.ExpectedSum + for i := 0; i < g_length; i++ { + api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_LINEAR) + // Equivavent constraint to the one below it, doesn't require GPoly[i][0] + // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) + e = api.Add(circuit.GPolynomials[i][0], api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) + } + api.AssertIsEqual(e, circuit.ValueAtChallengeVector) return nil } +func numOfCoeffsInMultilinearPolynomial(number_of_variables int) int { + return 1 << number_of_variables +} + +func sumArray(numbers []int) int { + result := 0 + for i := 0; i < len(numbers); i++ { + result += numbers[i] + } + return result +} + +func replace_r_in_f(f []int, r int) []int { + n := len(f) / 2 + for i := 0; i < n; i++ { + diff := f[n+i] - f[i] + scaled := r * diff + f[i] += scaled + } + return f[:n] +} + func main() { - var circuit Circuit + Init() + var number_of_variables = 3 + + // initialize coefficients + var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) + for i := 0; i < number_of_variables; i++ { + coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_LINEAR) + } + var challenge_vec = make([]frontend.Variable, number_of_variables) + var circuit = Circuit{ + GPolynomials: coeffs_univariate_polynomials, + ChallengeVector: challenge_vec, + } + ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) pk, vk, _ := groth16.Setup(ccs) - // ------ - R1, _ := new(big.Int).SetString("9256297558679035993185603119224026483248878132105160101344427504900917382708", 10) - R2, _ := new(big.Int).SetString("1501086694344315373207989466448958625613689647511317698257372243506299745486", 10) - G2_0, _ := new(big1Int).SetString("5880649804197832757310403612414804361198269995899445960335078328126943652508", 10) - G2_1, _ := new(big.Int).SetString("5010004099433259042870408211211164478295323719387463638651458302705939844619", 10) - - assignment := Circuit{ - Seed: 47, - C1: 34, - R1: R1, - R2: R2, - G_Coeffs: [4]frontend.Variable{1,3,7,10}, //g(x, y) := 1 + 3x + 7y + 10xy - G1_Coeffs: [2]frontend.Variable{9,16}, - G2_Coeffs: [2]frontend.Variable{G2_0, G2_1}, + + // f(x, y, z) = xy + yz + 2x + 3z + // polynomials are represented by their evals at {0,1}^3, ordered sequentially, (0,1,1) -> 4 + + var f = []int{0, 3, 0, 4, 2, 5, 3, 7} + + var initial_expected_sum = sumArray(f) + var expected_sum = sumArray(f) + var challenge_vector []frontend.Variable + + println(expected_sum) + + for i := 0; i < number_of_variables; i++ { + p_0 := sumArray(f[:len(f)/2]) + p_1 := expected_sum - p_0 - p_0 + coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1} + r := rand.Intn(11) + println("r_", i, " = ", r) + challenge_vector = append(challenge_vector, r) + f = replace_r_in_f(f, r) + expected_sum = p_0 + r*p_1 + } + + assignment := Circuit{ + ExpectedSum: initial_expected_sum, + ValueAtChallengeVector: expected_sum, + GPolynomials: coeffs_univariate_polynomials, + ChallengeVector: challenge_vector, } - // ------ witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) publicWitness, _ := witness.Public() proof, _ := groth16.Prove(ccs, pk, witness) From fcbf378c452d718328cab8c27a28e2c45fa8f362 Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Fri, 20 Sep 2024 15:37:45 +0200 Subject: [PATCH 2/6] initial R1CS drop --- go.mod | 1 + go.sum | 2 + main.go | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 160 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 0655839..f7ed776 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/rs/zerolog v1.30.0 // indirect github.com/x448/float16 v0.8.4 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sys v0.15.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index c41f1f4..81ca951 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index 9232c3b..4bf7dd7 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,12 @@ package main import ( "math/big" - "math/rand" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" + "golang.org/x/exp/rand" ) type Circuit struct { @@ -20,6 +20,8 @@ type Circuit struct { } const NUMBER_OF_COEFFS_IN_LINEAR = 2 +const NUMBER_OF_COEFFS_IN_QUADRATIC = 3 +const NUMBER_OF_COEFFS_IN_CUBIC = 4 var ONE_HALF_CONSTANT *big.Int @@ -33,15 +35,20 @@ func Init() { func (circuit *Circuit) Define(api frontend.API) error { // var manager = hashmanager.NewHashManager(api) - api.AssertIsEqual(circuit.ExpectedSum, api.Add(circuit.GPolynomials[0][0], api.Add(circuit.GPolynomials[0][0], circuit.GPolynomials[0][1]))) g_length := len(circuit.GPolynomials) api.AssertIsEqual(g_length, len(circuit.ChallengeVector)) e := circuit.ExpectedSum for i := 0; i < g_length; i++ { - api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_LINEAR) + // api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_LINEAR) + api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_CUBIC) + // Equivavent constraint to the one below it, doesn't require GPoly[i][0] // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) - e = api.Add(circuit.GPolynomials[i][0], api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) + cumulative := circuit.GPolynomials[i][NUMBER_OF_COEFFS_IN_CUBIC-1] + for j := NUMBER_OF_COEFFS_IN_CUBIC - 2; j >= 1; j-- { + cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, circuit.ChallengeVector[i])) + } + e = api.Add(circuit.GPolynomials[i][0], api.Mul(cumulative, circuit.ChallengeVector[i])) } api.AssertIsEqual(e, circuit.ValueAtChallengeVector) return nil @@ -71,12 +78,129 @@ func replace_r_in_f(f []int, r int) []int { func main() { Init() - var number_of_variables = 3 + + // START Basic case + // var number_of_variables = 3 + + // // initialize coefficients + // var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) + // for i := 0; i < number_of_variables; i++ { + // coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_LINEAR) + // } + // var challenge_vec = make([]frontend.Variable, number_of_variables) + // var circuit = Circuit{ + // GPolynomials: coeffs_univariate_polynomials, + // ChallengeVector: challenge_vec, + // } + + // ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + // pk, vk, _ := groth16.Setup(ccs) + + // // f(x, y, z) = xy + yz + 2x + 3z + // // polynomials are represented by their evals at {0,1}^3, ordered sequentially, (0,1,1) -> 4 + + // var f = []int{0, 3, 0, 4, 2, 5, 3, 7} + + // var initial_expected_sum = sumArray(f) + // var expected_sum = sumArray(f) + // var challenge_vector []frontend.Variable + + // println(expected_sum) + + // for i := 0; i < number_of_variables; i++ { + // p_0 := sumArray(f[:len(f)/2]) + // p_1 := expected_sum - p_0 - p_0 + // coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1} + // r := rand.Intn(11) + // println("r_", i, " = ", r) + // challenge_vector = append(challenge_vector, r) + // f = replace_r_in_f(f, r) + // expected_sum = p_0 + r*p_1 + // } + + // assignment := Circuit{ + // ExpectedSum: initial_expected_sum, + // ValueAtChallengeVector: expected_sum, + // GPolynomials: coeffs_univariate_polynomials, + // ChallengeVector: challenge_vector, + // } + // witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + // publicWitness, _ := witness.Public() + // proof, _ := groth16.Prove(ccs, pk, witness) + // groth16.Verify(proof, vk, publicWitness) + + // END Basic case + + // START A bit more advanced case + // Sum_x f(x) * g(x) + + // var number_of_variables = 2 + + // // initialize coefficients + // var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) + // for i := 0; i < number_of_variables; i++ { + // coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_QUADRATIC) + // } + // var challenge_vec = make([]frontend.Variable, number_of_variables) + // var circuit = Circuit{ + // GPolynomials: coeffs_univariate_polynomials, + // ChallengeVector: challenge_vec, + // } + + // ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + // pk, vk, _ := groth16.Setup(ccs) + + // // f(x, y) = 2x + 3y + 1 + // // g(x, y) = x + xy + 2y + // // polynomials are represented by their evals at {0,1}^2, ordered sequentially, (0,1) -> 4*2 = 8 + + // var f = []int{1, 4, 3, 6} + // var g = []int{0, 2, 1, 4} + // var f_g = []int{0, 8, 3, 24} + // var initial_expected_sum = sumArray(f_g) + // var expected_sum = initial_expected_sum + // var challenge_vector []frontend.Variable + + // println(expected_sum) + + // for i := 0; i < number_of_variables; i++ { + // p_0 := 0 + // p_2 := 0 + // for j := 0; j < len(f)/2; j++ { + // p_0 += f[j] * g[j] + // p_2 += (f[j+(len(f)/2)] - f[j]) * (g[j+(len(g)/2)] - g[j]) + // } + + // p_1 := expected_sum - p_0 - p_0 - p_2 + // coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2} + // r := rand.Intn(11) + // println("r_", i, " = ", r) + // challenge_vector = append(challenge_vector, r) + // f = replace_r_in_f(f, r) + // g = replace_r_in_f(g, r) + // expected_sum = p_0 + r*(p_1+r*p_2) + // } + + // assignment := Circuit{ + // ExpectedSum: initial_expected_sum, + // ValueAtChallengeVector: expected_sum, + // GPolynomials: coeffs_univariate_polynomials, + // ChallengeVector: challenge_vector, + // } + // witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + // publicWitness, _ := witness.Public() + // proof, _ := groth16.Prove(ccs, pk, witness) + // groth16.Verify(proof, vk, publicWitness) + // END A bit more advanced case + + // START R1CS case + // Sum_x e(x) * (a(x) * b(x) - c(x)) + var number_of_variables = 2 // initialize coefficients var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) for i := 0; i < number_of_variables; i++ { - coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_LINEAR) + coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_CUBIC) } var challenge_vec = make([]frontend.Variable, number_of_variables) var circuit = Circuit{ @@ -86,27 +210,41 @@ func main() { ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) pk, vk, _ := groth16.Setup(ccs) + // proof for some random values of e, Az, Bz, Cz + // still to validate for real A,B,C and its witness vector - // f(x, y, z) = xy + yz + 2x + 3z - // polynomials are represented by their evals at {0,1}^3, ordered sequentially, (0,1,1) -> 4 - - var f = []int{0, 3, 0, 4, 2, 5, 3, 7} - - var initial_expected_sum = sumArray(f) - var expected_sum = sumArray(f) + var e = []int{1, 4, 3, 6} + var a_z = []int{0, 2, 1, 4} + var b_z = []int{0, 2, 1, 4} + var c_z = []int{0, 2, 1, 4} + var final = []int{0, 16, 0, 6 * 12} + var initial_expected_sum = sumArray(final) + var expected_sum = initial_expected_sum var challenge_vector []frontend.Variable println(expected_sum) for i := 0; i < number_of_variables; i++ { - p_0 := sumArray(f[:len(f)/2]) - p_1 := expected_sum - p_0 - p_0 - coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1} + p_0 := 0 + p_tmp := 0 + p_3 := 0 + offset := len(e) / 2 + for j := 0; j < len(e)/2; j++ { + p_0 += e[j] * (a_z[j]*a_z[j] - a_z[j]) + p_tmp += (2*e[j] - e[j+offset]) * ((2*a_z[j]-a_z[j+offset])*(2*b_z[j]-b_z[j+offset]) - (2*c_z[j] - c_z[j+offset])) + p_3 += (e[j+offset] - e[j]) * (a_z[j+offset] - a_z[j]) * (b_z[j+offset] - b_z[j]) + } + p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 + p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 + coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2, p_3} r := rand.Intn(11) println("r_", i, " = ", r) challenge_vector = append(challenge_vector, r) - f = replace_r_in_f(f, r) - expected_sum = p_0 + r*p_1 + e = replace_r_in_f(e, r) + a_z = replace_r_in_f(a_z, r) + b_z = replace_r_in_f(b_z, r) + c_z = replace_r_in_f(c_z, r) + expected_sum = p_0 + r*(p_1+r*(p_2+r*p_3)) } assignment := Circuit{ @@ -119,4 +257,5 @@ func main() { publicWitness, _ := witness.Public() proof, _ := groth16.Prove(ccs, pk, witness) groth16.Verify(proof, vk, publicWitness) + //END R1CS case } From 38215224a091c6b2c482ad7881f19f022b5c736b Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Thu, 3 Oct 2024 13:09:34 +0200 Subject: [PATCH 3/6] wip --- go.mod | 29 ++++++++------ go.sum | 74 +++++++++++++++++------------------ hashmanager/hashmanager.go | 31 +++++++++++++++ main.go | 24 +++++++++--- r1cs.go | 80 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 54 deletions(-) create mode 100644 hashmanager/hashmanager.go create mode 100644 r1cs.go diff --git a/go.mod b/go.mod index f7ed776..3b48d50 100644 --- a/go.mod +++ b/go.mod @@ -3,25 +3,32 @@ module tutorial/sumcheck-verifier-circuit go 1.22.5 require ( - github.com/consensys/gnark v0.10.0 - github.com/consensys/gnark-crypto v0.13.0 + github.com/consensys/gnark v0.11.0 + github.com/consensys/gnark-crypto v0.14.0 github.com/vocdoni/gnark-crypto-primitives v0.0.1 ) require ( - github.com/bits-and-blooms/bitset v1.8.0 // indirect + github.com/iden3/go-iden3-crypto v0.0.17 // indirect + github.com/ronanh/intcomp v1.1.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sync v0.8.0 // indirect +) + +require ( + github.com/bits-and-blooms/bitset v1.14.3 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/fxamacker/cbor/v2 v2.5.0 // indirect - github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect - github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect - github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect + github.com/consensys/bavard v0.1.22 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d // indirect + github.com/ingonyama-zk/icicle v1.1.0 // indirect + github.com/ingonyama-zk/iciclegnark v0.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/rs/zerolog v1.30.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.25.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 81ca951..1a04f73 100644 --- a/go.sum +++ b/go.sum @@ -1,66 +1,66 @@ -github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= -github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.14.3 h1:Gd2c8lSNf9pKXom5JtD7AaKO8o7fGQ2LtFj1436qilA= +github.com/bits-and-blooms/bitset v1.14.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.10.0 h1:yhi6ThoeFP7WrH8zQDaO56WVXe9iJEBSkfrZ9PZxabw= -github.com/consensys/gnark v0.10.0/go.mod h1:VJU5JrrhZorbfDH+EUjcuFWr2c5z19tHPh8D6KVQksU= -github.com/consensys/gnark-crypto v0.13.0 h1:VPULb/v6bbYELAPTDFINEVaMTTybV5GLxDdcjnS+4oc= -github.com/consensys/gnark-crypto v0.13.0/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= +github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A= +github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/gnark v0.11.0 h1:YlndnlbRAoIEA+aIIHzNIW4P0dCIOM9/jCVzsXf356c= +github.com/consensys/gnark v0.11.0/go.mod h1:2LbheIOxsBI1a9Ck1XxUoy6PRnH28mSI9qrvtN2HwDY= +github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= +github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d h1:Jaz2JzpQaQXyET0AjLBXShrthbpqMkhGiEfkcQAiAUs= +github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= -github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= -github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 h1:YxI1RTPzpFJ3MBmxPl3Bo0F7ume7CmQEC1M9jL6CT94= -github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= -github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= -github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/iden3/go-iden3-crypto v0.0.17 h1:NdkceRLJo/pI4UpcjVah4lN/a3yzxRUGXqxbWcYh9mY= +github.com/iden3/go-iden3-crypto v0.0.17/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= +github.com/ingonyama-zk/icicle v1.1.0 h1:a2MUIaF+1i4JY2Lnb961ZMvaC8GFs9GqZgSnd9e95C8= +github.com/ingonyama-zk/icicle v1.1.0/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= +github.com/ingonyama-zk/iciclegnark v0.1.1 h1:BugVGAkKFu2uy02cRsgQdsE18VaFIJz55dBeZQJl4R0= +github.com/ingonyama-zk/iciclegnark v0.1.1/go.mod h1:g17CDuMfNBiN4hhZ4aA0rGF24Abv5GBFHJqE7aLxaZQ= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/ronanh/intcomp v1.1.0 h1:i54kxmpmSoOZFcWPMWryuakN0vLxLswASsGa07zkvLU= +github.com/ronanh/intcomp v1.1.0/go.mod h1:7FOLy3P3Zj3er/kVrU/pl+Ql7JFZj7bwliMGketo0IU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vocdoni/gnark-crypto-primitives v0.0.1 h1:RmxfYvHCFI1lnSPs07ZSTVNpoj0qrQSaNXwkh6vqcRg= github.com/vocdoni/gnark-crypto-primitives v0.0.1/go.mod h1:0rxBVlF+OY7EnoDatCPMTxrY6FzxNkyc4c4sweIvTRQ= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/hashmanager/hashmanager.go b/hashmanager/hashmanager.go new file mode 100644 index 0000000..3128118 --- /dev/null +++ b/hashmanager/hashmanager.go @@ -0,0 +1,31 @@ +package hashmanager + +import ( + "github.com/consensys/gnark/frontend" + "github.com/vocdoni/gnark-crypto-primitives/poseidon" +) + +type HashManager struct { + poseidonInstance poseidon.Poseidon + HashCollector []frontend.Variable + api frontend.API +} + +func NewHashManager(api frontend.API) *HashManager { + manager := new(HashManager) + manager.poseidonInstance = poseidon.NewPoseidon(api) + manager.HashCollector = []frontend.Variable{} + return manager +} + +func (manager *HashManager) WriteInput(inputs ...frontend.Variable) { + manager.poseidonInstance.Write(inputs...) +} + +func (manager *HashManager) WriteInputAndCollectAndReturnHash(inputs ...frontend.Variable) frontend.Variable { + manager.poseidonInstance.Write(inputs...) + hashUntilNow := manager.poseidonInstance.Sum() + manager.HashCollector = append(manager.HashCollector, hashUntilNow) + manager.poseidonInstance.Write(hashUntilNow) + return hashUntilNow +} diff --git a/main.go b/main.go index 4bf7dd7..cd6687c 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,13 @@ package main import ( "math/big" + "tutorial/sumcheck-verifier-circuit/hashmanager" "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/iden3/go-iden3-crypto/poseidon" "golang.org/x/exp/rand" ) @@ -34,7 +36,7 @@ func Init() { } func (circuit *Circuit) Define(api frontend.API) error { - // var manager = hashmanager.NewHashManager(api) + var manager = hashmanager.NewHashManager(api) g_length := len(circuit.GPolynomials) api.AssertIsEqual(g_length, len(circuit.ChallengeVector)) e := circuit.ExpectedSum @@ -44,6 +46,10 @@ func (circuit *Circuit) Define(api frontend.API) error { // Equivavent constraint to the one below it, doesn't require GPoly[i][0] // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) + // println("hash preimage: ", circuit.GPolynomials[i][0]) + api.Println(circuit.GPolynomials[i][0]) + hashUntilNow := manager.WriteInputAndCollectAndReturnHash(circuit.GPolynomials[i][0]) + api.Println(hashUntilNow) cumulative := circuit.GPolynomials[i][NUMBER_OF_COEFFS_IN_CUBIC-1] for j := NUMBER_OF_COEFFS_IN_CUBIC - 2; j >= 1; j-- { cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, circuit.ChallengeVector[i])) @@ -213,11 +219,14 @@ func main() { // proof for some random values of e, Az, Bz, Cz // still to validate for real A,B,C and its witness vector - var e = []int{1, 4, 3, 6} - var a_z = []int{0, 2, 1, 4} - var b_z = []int{0, 2, 1, 4} - var c_z = []int{0, 2, 1, 4} - var final = []int{0, 16, 0, 6 * 12} + VerifyR1CS() + + var e = []int{1, 4, 3, 6, 3, 5} + + var a_z = []int{3, 9, 30, 25, 5, 25} + var b_z = []int{3, 3, 1, 1, 5, 1} + var c_z = []int{9, 27, 30, 25, 25, 25} + var final = []int{0, 324, 180, 750, 150, 500} var initial_expected_sum = sumArray(final) var expected_sum = initial_expected_sum var challenge_vector []frontend.Variable @@ -236,7 +245,10 @@ func main() { } p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 + println("P_0 = ", p_0) coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2, p_3} + // println("============") + println(poseidon.Hash([]*big.Int{})) r := rand.Intn(11) println("r_", i, " = ", r) challenge_vector = append(challenge_vector, r) diff --git a/r1cs.go b/r1cs.go new file mode 100644 index 0000000..a37ba36 --- /dev/null +++ b/r1cs.go @@ -0,0 +1,80 @@ +package main + +import ( + "fmt" +) + +func VerifyR1CS() { + const numConstraints = 6 + const numVariables = 8 + + //row-major order + a := []int{ + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + -5, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + } + + b := []int{ + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + } + + c := []int{ + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 1, + } + + // Witness + z := []int{ + 1, + 3, + 9, + 27, + 30, + 25, + 5, + 25, + } + + valid := true + for i := 0; i < numConstraints; i++ { + + Aiz := 0 + Biz := 0 + Ciz := 0 + + for j := 0; j < numVariables; j++ { + index := i*numVariables + j + Aiz += a[index] * z[j] + Biz += b[index] * z[j] + Ciz += c[index] * z[j] + } + + if Aiz*Biz != Ciz { + valid = false + fmt.Printf("Constraint %d failed: (A_i z) * (B_i z) != C_i z\n", i+1) + fmt.Printf("A_i z = %d, B_i z = %d, C_i z = %d\n", Aiz, Biz, Ciz) + } else { + fmt.Printf("Constraint %d passed: (A_i z) * (B_i z) = C_i z\n", i+1) + fmt.Printf("A_i z = %d, B_i z = %d, C_i z = %d\n", Aiz, Biz, Ciz) + } + } + + if valid { + fmt.Println("All constraints are satisfied.") + } else { + fmt.Println("Some constraints are not satisfied.") + } +} From ed9168eac100f0280dba7aacc59fc75d85ea0378 Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Thu, 3 Oct 2024 14:23:38 +0200 Subject: [PATCH 4/6] remove challenge vector, use hash instead --- hashmanager/hashmanager.go | 4 +- main.go | 306 +++++++++++++++++-------------------- 2 files changed, 143 insertions(+), 167 deletions(-) diff --git a/hashmanager/hashmanager.go b/hashmanager/hashmanager.go index 3128118..e2df2b9 100644 --- a/hashmanager/hashmanager.go +++ b/hashmanager/hashmanager.go @@ -25,7 +25,7 @@ func (manager *HashManager) WriteInput(inputs ...frontend.Variable) { func (manager *HashManager) WriteInputAndCollectAndReturnHash(inputs ...frontend.Variable) frontend.Variable { manager.poseidonInstance.Write(inputs...) hashUntilNow := manager.poseidonInstance.Sum() - manager.HashCollector = append(manager.HashCollector, hashUntilNow) - manager.poseidonInstance.Write(hashUntilNow) + // manager.HashCollector = append(manager.HashCollector, hashUntilNow) + // manager.poseidonInstance.Write(hashUntilNow) return hashUntilNow } diff --git a/main.go b/main.go index cd6687c..a3eb3ce 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "math/big" "tutorial/sumcheck-verifier-circuit/hashmanager" @@ -9,14 +10,12 @@ import ( "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/iden3/go-iden3-crypto/poseidon" - "golang.org/x/exp/rand" ) type Circuit struct { // Alleged computed sum of all the evaluations - ExpectedSum frontend.Variable `gnark:"ExpectedSum"` - ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` - ChallengeVector []frontend.Variable `gnark:"ChallengeVector"` + ExpectedSum frontend.Variable `gnark:"ExpectedSum"` + ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` // Array of elements representing the values of p0, p1 in each of the rounds GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` } @@ -25,59 +24,54 @@ const NUMBER_OF_COEFFS_IN_LINEAR = 2 const NUMBER_OF_COEFFS_IN_QUADRATIC = 3 const NUMBER_OF_COEFFS_IN_CUBIC = 4 +var MOD *big.Int var ONE_HALF_CONSTANT *big.Int func Init() { var success bool + MOD, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) ONE_HALF_CONSTANT, success = new(big.Int).SetString("10944121435919637611123202872628637544274182200208017171849102093287904247809", 10) if !success { - println("Error: Failed to set big.Int value") + fmt.Println("Error: Failed to set big.Int value") } } func (circuit *Circuit) Define(api frontend.API) error { var manager = hashmanager.NewHashManager(api) g_length := len(circuit.GPolynomials) - api.AssertIsEqual(g_length, len(circuit.ChallengeVector)) e := circuit.ExpectedSum for i := 0; i < g_length; i++ { - // api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_LINEAR) api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_CUBIC) - // Equivavent constraint to the one below it, doesn't require GPoly[i][0] + // Equivalent constraint to the one below it, doesn't require GPoly[i][0] // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) - // println("hash preimage: ", circuit.GPolynomials[i][0]) - api.Println(circuit.GPolynomials[i][0]) - hashUntilNow := manager.WriteInputAndCollectAndReturnHash(circuit.GPolynomials[i][0]) - api.Println(hashUntilNow) + api.Println(circuit.GPolynomials[i][0], circuit.GPolynomials[i][1]) + r_i := manager.WriteInputAndCollectAndReturnHash(circuit.GPolynomials[i]...) + api.Println(r_i) cumulative := circuit.GPolynomials[i][NUMBER_OF_COEFFS_IN_CUBIC-1] for j := NUMBER_OF_COEFFS_IN_CUBIC - 2; j >= 1; j-- { - cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, circuit.ChallengeVector[i])) + cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, r_i)) } - e = api.Add(circuit.GPolynomials[i][0], api.Mul(cumulative, circuit.ChallengeVector[i])) + e = api.Add(circuit.GPolynomials[i][0], api.Mul(cumulative, r_i)) } api.AssertIsEqual(e, circuit.ValueAtChallengeVector) return nil } -func numOfCoeffsInMultilinearPolynomial(number_of_variables int) int { - return 1 << number_of_variables -} - -func sumArray(numbers []int) int { - result := 0 +func sumArray(numbers []*big.Int) *big.Int { + result := big.NewInt(0) for i := 0; i < len(numbers); i++ { - result += numbers[i] + result.Add(result, numbers[i]) } return result } -func replace_r_in_f(f []int, r int) []int { +func replace_r_in_f(f []*big.Int, r *big.Int) []*big.Int { n := len(f) / 2 for i := 0; i < n; i++ { - diff := f[n+i] - f[i] - scaled := r * diff - f[i] += scaled + diff := new(big.Int).Sub(f[n+i], f[i]) // diff = f[n+i] - f[i] + scaled := new(big.Int).Mul(r, diff) // scaled = r * diff + f[i].Add(f[i], scaled) // f[i] += scaled } return f[:n] } @@ -85,120 +79,6 @@ func replace_r_in_f(f []int, r int) []int { func main() { Init() - // START Basic case - // var number_of_variables = 3 - - // // initialize coefficients - // var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) - // for i := 0; i < number_of_variables; i++ { - // coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_LINEAR) - // } - // var challenge_vec = make([]frontend.Variable, number_of_variables) - // var circuit = Circuit{ - // GPolynomials: coeffs_univariate_polynomials, - // ChallengeVector: challenge_vec, - // } - - // ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - // pk, vk, _ := groth16.Setup(ccs) - - // // f(x, y, z) = xy + yz + 2x + 3z - // // polynomials are represented by their evals at {0,1}^3, ordered sequentially, (0,1,1) -> 4 - - // var f = []int{0, 3, 0, 4, 2, 5, 3, 7} - - // var initial_expected_sum = sumArray(f) - // var expected_sum = sumArray(f) - // var challenge_vector []frontend.Variable - - // println(expected_sum) - - // for i := 0; i < number_of_variables; i++ { - // p_0 := sumArray(f[:len(f)/2]) - // p_1 := expected_sum - p_0 - p_0 - // coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1} - // r := rand.Intn(11) - // println("r_", i, " = ", r) - // challenge_vector = append(challenge_vector, r) - // f = replace_r_in_f(f, r) - // expected_sum = p_0 + r*p_1 - // } - - // assignment := Circuit{ - // ExpectedSum: initial_expected_sum, - // ValueAtChallengeVector: expected_sum, - // GPolynomials: coeffs_univariate_polynomials, - // ChallengeVector: challenge_vector, - // } - // witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) - // publicWitness, _ := witness.Public() - // proof, _ := groth16.Prove(ccs, pk, witness) - // groth16.Verify(proof, vk, publicWitness) - - // END Basic case - - // START A bit more advanced case - // Sum_x f(x) * g(x) - - // var number_of_variables = 2 - - // // initialize coefficients - // var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) - // for i := 0; i < number_of_variables; i++ { - // coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_QUADRATIC) - // } - // var challenge_vec = make([]frontend.Variable, number_of_variables) - // var circuit = Circuit{ - // GPolynomials: coeffs_univariate_polynomials, - // ChallengeVector: challenge_vec, - // } - - // ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - // pk, vk, _ := groth16.Setup(ccs) - - // // f(x, y) = 2x + 3y + 1 - // // g(x, y) = x + xy + 2y - // // polynomials are represented by their evals at {0,1}^2, ordered sequentially, (0,1) -> 4*2 = 8 - - // var f = []int{1, 4, 3, 6} - // var g = []int{0, 2, 1, 4} - // var f_g = []int{0, 8, 3, 24} - // var initial_expected_sum = sumArray(f_g) - // var expected_sum = initial_expected_sum - // var challenge_vector []frontend.Variable - - // println(expected_sum) - - // for i := 0; i < number_of_variables; i++ { - // p_0 := 0 - // p_2 := 0 - // for j := 0; j < len(f)/2; j++ { - // p_0 += f[j] * g[j] - // p_2 += (f[j+(len(f)/2)] - f[j]) * (g[j+(len(g)/2)] - g[j]) - // } - - // p_1 := expected_sum - p_0 - p_0 - p_2 - // coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2} - // r := rand.Intn(11) - // println("r_", i, " = ", r) - // challenge_vector = append(challenge_vector, r) - // f = replace_r_in_f(f, r) - // g = replace_r_in_f(g, r) - // expected_sum = p_0 + r*(p_1+r*p_2) - // } - - // assignment := Circuit{ - // ExpectedSum: initial_expected_sum, - // ValueAtChallengeVector: expected_sum, - // GPolynomials: coeffs_univariate_polynomials, - // ChallengeVector: challenge_vector, - // } - // witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) - // publicWitness, _ := witness.Public() - // proof, _ := groth16.Prove(ccs, pk, witness) - // groth16.Verify(proof, vk, publicWitness) - // END A bit more advanced case - // START R1CS case // Sum_x e(x) * (a(x) * b(x) - c(x)) var number_of_variables = 2 @@ -208,10 +88,8 @@ func main() { for i := 0; i < number_of_variables; i++ { coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_CUBIC) } - var challenge_vec = make([]frontend.Variable, number_of_variables) var circuit = Circuit{ - GPolynomials: coeffs_univariate_polynomials, - ChallengeVector: challenge_vec, + GPolynomials: coeffs_univariate_polynomials, } ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) @@ -219,51 +97,149 @@ func main() { // proof for some random values of e, Az, Bz, Cz // still to validate for real A,B,C and its witness vector - VerifyR1CS() + // Commented out since VerifyR1CS() is not defined in the provided code + // VerifyR1CS() + + // Initialize arrays with *big.Int + var e = []*big.Int{ + big.NewInt(1), + big.NewInt(4), + big.NewInt(3), + big.NewInt(6), + big.NewInt(3), + big.NewInt(5), + } - var e = []int{1, 4, 3, 6, 3, 5} + var a_z = []*big.Int{ + big.NewInt(3), + big.NewInt(9), + big.NewInt(30), + big.NewInt(25), + big.NewInt(5), + big.NewInt(25), + } + + var b_z = []*big.Int{ + big.NewInt(3), + big.NewInt(3), + big.NewInt(1), + big.NewInt(1), + big.NewInt(5), + big.NewInt(1), + } + + var c_z = []*big.Int{ + big.NewInt(9), + big.NewInt(27), + big.NewInt(30), + big.NewInt(25), + big.NewInt(25), + big.NewInt(25), + } + + var final = []*big.Int{ + big.NewInt(0), + big.NewInt(324), + big.NewInt(180), + big.NewInt(750), + big.NewInt(150), + big.NewInt(500), + } - var a_z = []int{3, 9, 30, 25, 5, 25} - var b_z = []int{3, 3, 1, 1, 5, 1} - var c_z = []int{9, 27, 30, 25, 25, 25} - var final = []int{0, 324, 180, 750, 150, 500} var initial_expected_sum = sumArray(final) - var expected_sum = initial_expected_sum + var expected_sum = new(big.Int).Set(initial_expected_sum) var challenge_vector []frontend.Variable - println(expected_sum) + fmt.Println("Initial Expected Sum:", expected_sum) for i := 0; i < number_of_variables; i++ { - p_0 := 0 - p_tmp := 0 - p_3 := 0 + p_0 := big.NewInt(0) + p_tmp := big.NewInt(0) + p_3 := big.NewInt(0) offset := len(e) / 2 for j := 0; j < len(e)/2; j++ { - p_0 += e[j] * (a_z[j]*a_z[j] - a_z[j]) - p_tmp += (2*e[j] - e[j+offset]) * ((2*a_z[j]-a_z[j+offset])*(2*b_z[j]-b_z[j+offset]) - (2*c_z[j] - c_z[j+offset])) - p_3 += (e[j+offset] - e[j]) * (a_z[j+offset] - a_z[j]) * (b_z[j+offset] - b_z[j]) + // p_0 += e[j] * (a_z[j]*a_z[j] - a_z[j]) + temp1 := new(big.Int).Mul(a_z[j], a_z[j]) // a_z[j]*a_z[j] + temp1.Sub(temp1, a_z[j]) // temp1 = temp1 - a_z[j] + temp1.Mul(temp1, e[j]) // temp1 = e[j] * (a_z[j]*a_z[j] - a_z[j]) + p_0.Add(p_0, temp1) + p_0.Mod(temp1, MOD) + + // p_tmp += (2*e[j] - e[j+offset]) * ((2*a_z[j]-a_z[j+offset])*(2*b_z[j]-b_z[j+offset]) - (2*c_z[j] - c_z[j+offset])) + temp2 := new(big.Int).Mul(big.NewInt(2), e[j]) // 2*e[j] + temp2.Sub(temp2, e[j+offset]) // temp2 = (2*e[j] - e[j+offset]) + + temp3 := new(big.Int).Mul(big.NewInt(2), a_z[j]) // 2*a_z[j] + temp3.Sub(temp3, a_z[j+offset]) // temp3 = (2*a_z[j] - a_z[j+offset]) + + temp4 := new(big.Int).Mul(big.NewInt(2), b_z[j]) // 2*b_z[j] + temp4.Sub(temp4, b_z[j+offset]) // temp4 = (2*b_z[j] - b_z[j+offset]) + + temp5 := new(big.Int).Mul(temp3, temp4) // temp5 = temp3 * temp4 + + temp6 := new(big.Int).Mul(big.NewInt(2), c_z[j]) // 2*c_z[j] + temp6.Sub(temp6, c_z[j+offset]) // temp6 = (2*c_z[j] - c_z[j+offset]) + + temp7 := new(big.Int).Sub(temp5, temp6) // temp7 = temp5 - temp6 + + temp8 := new(big.Int).Mul(temp2, temp7) // temp8 = temp2 * temp7 + + p_tmp.Add(p_tmp, temp8) + p_tmp.Mod(p_tmp, MOD) + + // p_3 += (e[j+offset] - e[j]) * (a_z[j+offset] - a_z[j]) * (b_z[j+offset] - b_z[j]) + temp9 := new(big.Int).Sub(e[j+offset], e[j]) // temp9 = e[j+offset] - e[j] + temp10 := new(big.Int).Sub(a_z[j+offset], a_z[j]) // temp10 = a_z[j+offset] - a_z[j] + temp11 := new(big.Int).Sub(b_z[j+offset], b_z[j]) // temp11 = b_z[j+offset] - b_z[j] + + temp12 := new(big.Int).Mul(temp9, temp10) + temp12.Mul(temp12, temp11) + + p_3.Add(p_3, temp12) + p_3.Mod(p_3, MOD) } - p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 - p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 - println("P_0 = ", p_0) + + // p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 + temp13 := new(big.Int).Add(expected_sum, p_tmp) + temp13.Sub(temp13, p_0) + temp13.Sub(temp13, p_0) + temp13.Sub(temp13, p_0) + + p_2 := new(big.Int).Div(temp13, big.NewInt(2)) + p_2.Mod(p_2, MOD) + // p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 + p_1 := new(big.Int).Sub(expected_sum, p_0) + p_1.Sub(p_1, p_0) + p_1.Sub(p_1, p_3) + p_1.Sub(p_1, p_2) + p_1.Mod(p_1, MOD) + coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2, p_3} - // println("============") - println(poseidon.Hash([]*big.Int{})) - r := rand.Intn(11) - println("r_", i, " = ", r) + hash_value, _ := poseidon.Hash([]*big.Int{p_0, p_1, p_2, p_3}) + // Generate a random *big.Int less than 11 + r := hash_value + fmt.Println("r_", i, " = ", r) challenge_vector = append(challenge_vector, r) + e = replace_r_in_f(e, r) a_z = replace_r_in_f(a_z, r) b_z = replace_r_in_f(b_z, r) c_z = replace_r_in_f(c_z, r) - expected_sum = p_0 + r*(p_1+r*(p_2+r*p_3)) + + // expected_sum = p_0 + r*(p_1 + r*(p_2 + r*p_3)) + temp14 := new(big.Int).Mul(r, p_3) // r * p_3 + temp14.Add(temp14, p_2) // p_2 + r * p_3 + temp14.Mul(temp14, r) // r * (p_2 + r * p_3) + temp14.Add(temp14, p_1) // p_1 + r * (p_2 + r * p_3) + temp14.Mul(temp14, r) // r * (p_1 + r * (p_2 + r * p_3)) + expected_sum = new(big.Int).Add(p_0, temp14) + expected_sum.Mod(expected_sum, MOD) } assignment := Circuit{ ExpectedSum: initial_expected_sum, ValueAtChallengeVector: expected_sum, GPolynomials: coeffs_univariate_polynomials, - ChallengeVector: challenge_vector, } witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) publicWitness, _ := witness.Public() From f8c5296d8a4f37fadf9b2a51fb206e4ec8c89ba2 Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Fri, 18 Oct 2024 16:57:37 +0200 Subject: [PATCH 5/6] merkle tree checks --- hashmanager/hashmanager.go | 1 + main.go | 50 +++++++++--------- verify_merkle.go | 103 +++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 verify_merkle.go diff --git a/hashmanager/hashmanager.go b/hashmanager/hashmanager.go index e2df2b9..5a7557a 100644 --- a/hashmanager/hashmanager.go +++ b/hashmanager/hashmanager.go @@ -27,5 +27,6 @@ func (manager *HashManager) WriteInputAndCollectAndReturnHash(inputs ...frontend hashUntilNow := manager.poseidonInstance.Sum() // manager.HashCollector = append(manager.HashCollector, hashUntilNow) // manager.poseidonInstance.Write(hashUntilNow) + manager.poseidonInstance.Reset() return hashUntilNow } diff --git a/main.go b/main.go index a3eb3ce..385252d 100644 --- a/main.go +++ b/main.go @@ -12,14 +12,6 @@ import ( "github.com/iden3/go-iden3-crypto/poseidon" ) -type Circuit struct { - // Alleged computed sum of all the evaluations - ExpectedSum frontend.Variable `gnark:"ExpectedSum"` - ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` - // Array of elements representing the values of p0, p1 in each of the rounds - GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` -} - const NUMBER_OF_COEFFS_IN_LINEAR = 2 const NUMBER_OF_COEFFS_IN_QUADRATIC = 3 const NUMBER_OF_COEFFS_IN_CUBIC = 4 @@ -36,6 +28,14 @@ func Init() { } } +type Circuit struct { + // Alleged computed sum of all the evaluations + ExpectedSum frontend.Variable `gnark:"ExpectedSum"` + ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` + // Array of elements representing the values of p0, p1 in each of the rounds + GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` +} + func (circuit *Circuit) Define(api frontend.API) error { var manager = hashmanager.NewHashManager(api) g_length := len(circuit.GPolynomials) @@ -58,10 +58,13 @@ func (circuit *Circuit) Define(api frontend.API) error { return nil } -func sumArray(numbers []*big.Int) *big.Int { +func calculateCubic(e []*big.Int, a_z []*big.Int, b_z []*big.Int, c_z []*big.Int) *big.Int { result := big.NewInt(0) - for i := 0; i < len(numbers); i++ { - result.Add(result, numbers[i]) + for i := 0; i < len(e); i++ { + tmp := new(big.Int).Mul(a_z[i], b_z[i]) + tmp.Sub(tmp, c_z[i]) + tmp.Mul(tmp, e[i]) + result.Add(result, tmp) } return result } @@ -108,6 +111,8 @@ func main() { big.NewInt(6), big.NewInt(3), big.NewInt(5), + big.NewInt(0), + big.NewInt(0), } var a_z = []*big.Int{ @@ -117,6 +122,8 @@ func main() { big.NewInt(25), big.NewInt(5), big.NewInt(25), + big.NewInt(0), + big.NewInt(0), } var b_z = []*big.Int{ @@ -126,6 +133,8 @@ func main() { big.NewInt(1), big.NewInt(5), big.NewInt(1), + big.NewInt(0), + big.NewInt(0), } var c_z = []*big.Int{ @@ -135,18 +144,11 @@ func main() { big.NewInt(25), big.NewInt(25), big.NewInt(25), - } - - var final = []*big.Int{ big.NewInt(0), - big.NewInt(324), - big.NewInt(180), - big.NewInt(750), - big.NewInt(150), - big.NewInt(500), + big.NewInt(0), } - var initial_expected_sum = sumArray(final) + var initial_expected_sum = calculateCubic(e, a_z, b_z, c_z) var expected_sum = new(big.Int).Set(initial_expected_sum) var challenge_vector []frontend.Variable @@ -158,10 +160,10 @@ func main() { p_3 := big.NewInt(0) offset := len(e) / 2 for j := 0; j < len(e)/2; j++ { - // p_0 += e[j] * (a_z[j]*a_z[j] - a_z[j]) - temp1 := new(big.Int).Mul(a_z[j], a_z[j]) // a_z[j]*a_z[j] - temp1.Sub(temp1, a_z[j]) // temp1 = temp1 - a_z[j] - temp1.Mul(temp1, e[j]) // temp1 = e[j] * (a_z[j]*a_z[j] - a_z[j]) + // p_0 += e[j] * (a_z[j]*b_z[j] - c_z[j]) + temp1 := new(big.Int).Mul(a_z[j], b_z[j]) // a_z[j]*a_z[j] + temp1.Sub(temp1, c_z[j]) // temp1 = temp1 - c_z[j] + temp1.Mul(temp1, e[j]) // temp1 = e[j] * (a_z[j]*b_z[j] - c_z[j]) p_0.Add(p_0, temp1) p_0.Mod(temp1, MOD) diff --git a/verify_merkle.go b/verify_merkle.go new file mode 100644 index 0000000..7df52a2 --- /dev/null +++ b/verify_merkle.go @@ -0,0 +1,103 @@ +package main + +import ( + "math/big" + "tutorial/sumcheck-verifier-circuit/hashmanager" + + "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/std/math/cmp" +) + +type VerifyMerkleProofCircuit struct { + // Inputs + Leaves []frontend.Variable + LeafIndexes []frontend.Variable + LeafSiblingHashes []frontend.Variable + AuthPathPrefixLenghts []frontend.Variable + AuthPathSuffixes [][]frontend.Variable //in Incremental Encoding + // Public Input + RootHash frontend.Variable `gnark:",public"` +} + +func DecodePrefixPath(api frontend.API, circuitPrevPath []frontend.Variable, circuitPrefixLen frontend.Variable, circuitSuffix []frontend.Variable) []frontend.Variable { + const maxPrevPathLen = 20 + const maxSuffixLen = 20 + comparator := cmp.NewBoundedComparator(api, big.NewInt(1<<32-1), false) + + const resultLen = maxPrevPathLen + maxSuffixLen + + prevPath := make([]frontend.Variable, maxPrevPathLen) + suffix := make([]frontend.Variable, maxSuffixLen) + result := make([]frontend.Variable, resultLen) + + for i := 0; i < maxPrevPathLen; i++ { + prevPath[i] = circuitPrevPath[i] + } + for i := 0; i < maxSuffixLen; i++ { + suffix[i] = circuitSuffix[i] + } + + for i := 0; i < resultLen; i++ { + iVar, _ := api.ConstantValue(uint64(i)) + + isLessThanPrefixLen := comparator.IsLess(iVar, circuitPrefixLen) + indexInSuffix := api.Sub(iVar, circuitPrefixLen) + isInSuffixRange := comparator.IsLess(indexInSuffix, maxSuffixLen) + + prevPathElement := api.Select(isLessThanPrefixLen, prevPath[i], frontend.Variable(0)) + suffixElement := api.Select(isInSuffixRange, suffix[indexInSuffix], frontend.Variable(0)) + + result[i] = api.Add(prevPathElement, suffixElement) + } + + return result +} + +func (circuit *VerifyMerkleProofCircuit) Define(api frontend.API) error { + const N = 100 + + var manager = hashmanager.NewHashManager(api) + numLeaves := len(circuit.Leaves) + // ``treeHeight := len(circuit.AuthPathSuffixes[0]) + 2 + + prevPath := circuit.AuthPathSuffixes[0] + for i := 0; i < numLeaves; i++ { + leaf := circuit.Leaves[i] + leafIndex := circuit.LeafIndexes[i] + leafSiblingHash := circuit.LeafSiblingHashes[i] + + // DecodePrefixPath(api) + authPath := prevPath + if circuit.AuthPathPrefixLenghts[i] == 0 { + authPath = circuit.AuthPathSuffixes[i] + } else { + + } + + claimedLeafHash := manager.WriteInputAndCollectAndReturnHash(leaf) + + dir := api.And(leafIndex, 1) + leftChild := api.Select(dir, leafSiblingHash, claimedLeafHash) + rightChild := api.Select(dir, claimedLeafHash, leafSiblingHash) + + currentHash := manager.WriteInputAndCollectAndReturnHash(leftChild, rightChild) + + index := api.Div(leafIndex, 2) + + for level := 0; level < len(authPath); level++ { + siblingHash := authPath[level] + + dir := api.And(index, 1) + left := api.Select(dir, siblingHash, currentHash) + right := api.Select(dir, currentHash, siblingHash) + + currentHash = manager.WriteInputAndCollectAndReturnHash(left, right) + + index = api.Div(index, 2) + } + + api.AssertIsEqual(currentHash, circuit.RootHash) + } + + return nil +} From 5cd6de19911ce785be731da7d0338e0923a42152 Mon Sep 17 00:00:00 2001 From: Veljko Vranic Date: Tue, 12 Nov 2024 14:06:03 +0100 Subject: [PATCH 6/6] current wip --- main.go | 273 +++++++++++------------------------------------ main_spartan.go | 251 +++++++++++++++++++++++++++++++++++++++++++ verify_merkle.go | 60 ++--------- 3 files changed, 318 insertions(+), 266 deletions(-) create mode 100644 main_spartan.go diff --git a/main.go b/main.go index 385252d..42d937c 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "math/big" "tutorial/sumcheck-verifier-circuit/hashmanager" @@ -9,243 +8,91 @@ import ( "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" - "github.com/iden3/go-iden3-crypto/poseidon" ) -const NUMBER_OF_COEFFS_IN_LINEAR = 2 -const NUMBER_OF_COEFFS_IN_QUADRATIC = 3 -const NUMBER_OF_COEFFS_IN_CUBIC = 4 - -var MOD *big.Int -var ONE_HALF_CONSTANT *big.Int - -func Init() { - var success bool - MOD, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) - ONE_HALF_CONSTANT, success = new(big.Int).SetString("10944121435919637611123202872628637544274182200208017171849102093287904247809", 10) - if !success { - fmt.Println("Error: Failed to set big.Int value") - } +type VerifyMerkleProofCircuit struct { + // Inputs + Leaves []frontend.Variable + LeafIndexes []frontend.Variable + LeafSiblingHashes []frontend.Variable + AuthPaths [][]frontend.Variable + // Public Input + RootHash frontend.Variable `gnark:",public"` } -type Circuit struct { - // Alleged computed sum of all the evaluations - ExpectedSum frontend.Variable `gnark:"ExpectedSum"` - ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` - // Array of elements representing the values of p0, p1 in each of the rounds - GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` -} - -func (circuit *Circuit) Define(api frontend.API) error { +func (circuit *VerifyMerkleProofCircuit) Define(api frontend.API) error { var manager = hashmanager.NewHashManager(api) - g_length := len(circuit.GPolynomials) - e := circuit.ExpectedSum - for i := 0; i < g_length; i++ { - api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_CUBIC) - - // Equivalent constraint to the one below it, doesn't require GPoly[i][0] - // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) - api.Println(circuit.GPolynomials[i][0], circuit.GPolynomials[i][1]) - r_i := manager.WriteInputAndCollectAndReturnHash(circuit.GPolynomials[i]...) - api.Println(r_i) - cumulative := circuit.GPolynomials[i][NUMBER_OF_COEFFS_IN_CUBIC-1] - for j := NUMBER_OF_COEFFS_IN_CUBIC - 2; j >= 1; j-- { - cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, r_i)) - } - e = api.Add(circuit.GPolynomials[i][0], api.Mul(cumulative, r_i)) - } - api.AssertIsEqual(e, circuit.ValueAtChallengeVector) - return nil -} - -func calculateCubic(e []*big.Int, a_z []*big.Int, b_z []*big.Int, c_z []*big.Int) *big.Int { - result := big.NewInt(0) - for i := 0; i < len(e); i++ { - tmp := new(big.Int).Mul(a_z[i], b_z[i]) - tmp.Sub(tmp, c_z[i]) - tmp.Mul(tmp, e[i]) - result.Add(result, tmp) - } - return result -} - -func replace_r_in_f(f []*big.Int, r *big.Int) []*big.Int { - n := len(f) / 2 - for i := 0; i < n; i++ { - diff := new(big.Int).Sub(f[n+i], f[i]) // diff = f[n+i] - f[i] - scaled := new(big.Int).Mul(r, diff) // scaled = r * diff - f[i].Add(f[i], scaled) // f[i] += scaled - } - return f[:n] -} - -func main() { - Init() - - // START R1CS case - // Sum_x e(x) * (a(x) * b(x) - c(x)) - var number_of_variables = 2 - - // initialize coefficients - var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) - for i := 0; i < number_of_variables; i++ { - coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_CUBIC) - } - var circuit = Circuit{ - GPolynomials: coeffs_univariate_polynomials, - } + numLeaves := len(circuit.Leaves) + // ``treeHeight := len(circuit.AuthPathSuffixes[0]) + 2 - ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - pk, vk, _ := groth16.Setup(ccs) - // proof for some random values of e, Az, Bz, Cz - // still to validate for real A,B,C and its witness vector - - // Commented out since VerifyR1CS() is not defined in the provided code - // VerifyR1CS() - - // Initialize arrays with *big.Int - var e = []*big.Int{ - big.NewInt(1), - big.NewInt(4), - big.NewInt(3), - big.NewInt(6), - big.NewInt(3), - big.NewInt(5), - big.NewInt(0), - big.NewInt(0), - } - - var a_z = []*big.Int{ - big.NewInt(3), - big.NewInt(9), - big.NewInt(30), - big.NewInt(25), - big.NewInt(5), - big.NewInt(25), - big.NewInt(0), - big.NewInt(0), - } - - var b_z = []*big.Int{ - big.NewInt(3), - big.NewInt(3), - big.NewInt(1), - big.NewInt(1), - big.NewInt(5), - big.NewInt(1), - big.NewInt(0), - big.NewInt(0), - } - - var c_z = []*big.Int{ - big.NewInt(9), - big.NewInt(27), - big.NewInt(30), - big.NewInt(25), - big.NewInt(25), - big.NewInt(25), - big.NewInt(0), - big.NewInt(0), - } + for i := 0; i < numLeaves; i++ { + leaf := circuit.Leaves[i] + leafIndex := circuit.LeafIndexes[i] + leafSiblingHash := circuit.LeafSiblingHashes[i] - var initial_expected_sum = calculateCubic(e, a_z, b_z, c_z) - var expected_sum = new(big.Int).Set(initial_expected_sum) - var challenge_vector []frontend.Variable + authPath := circuit.AuthPaths[i] - fmt.Println("Initial Expected Sum:", expected_sum) + claimedLeafHash := manager.WriteInputAndCollectAndReturnHash(leaf) - for i := 0; i < number_of_variables; i++ { - p_0 := big.NewInt(0) - p_tmp := big.NewInt(0) - p_3 := big.NewInt(0) - offset := len(e) / 2 - for j := 0; j < len(e)/2; j++ { - // p_0 += e[j] * (a_z[j]*b_z[j] - c_z[j]) - temp1 := new(big.Int).Mul(a_z[j], b_z[j]) // a_z[j]*a_z[j] - temp1.Sub(temp1, c_z[j]) // temp1 = temp1 - c_z[j] - temp1.Mul(temp1, e[j]) // temp1 = e[j] * (a_z[j]*b_z[j] - c_z[j]) - p_0.Add(p_0, temp1) - p_0.Mod(temp1, MOD) - - // p_tmp += (2*e[j] - e[j+offset]) * ((2*a_z[j]-a_z[j+offset])*(2*b_z[j]-b_z[j+offset]) - (2*c_z[j] - c_z[j+offset])) - temp2 := new(big.Int).Mul(big.NewInt(2), e[j]) // 2*e[j] - temp2.Sub(temp2, e[j+offset]) // temp2 = (2*e[j] - e[j+offset]) + dir := api.And(leafIndex, 1) + leftChild := api.Select(dir, leafSiblingHash, claimedLeafHash) + rightChild := api.Select(dir, claimedLeafHash, leafSiblingHash) - temp3 := new(big.Int).Mul(big.NewInt(2), a_z[j]) // 2*a_z[j] - temp3.Sub(temp3, a_z[j+offset]) // temp3 = (2*a_z[j] - a_z[j+offset]) + currentHash := manager.WriteInputAndCollectAndReturnHash(leftChild, rightChild) - temp4 := new(big.Int).Mul(big.NewInt(2), b_z[j]) // 2*b_z[j] - temp4.Sub(temp4, b_z[j+offset]) // temp4 = (2*b_z[j] - b_z[j+offset]) + index := api.Div(leafIndex, 2) - temp5 := new(big.Int).Mul(temp3, temp4) // temp5 = temp3 * temp4 + for level := 0; level < len(authPath); level++ { + siblingHash := authPath[level] - temp6 := new(big.Int).Mul(big.NewInt(2), c_z[j]) // 2*c_z[j] - temp6.Sub(temp6, c_z[j+offset]) // temp6 = (2*c_z[j] - c_z[j+offset]) + dir := api.And(index, 1) + left := api.Select(dir, siblingHash, currentHash) + right := api.Select(dir, currentHash, siblingHash) - temp7 := new(big.Int).Sub(temp5, temp6) // temp7 = temp5 - temp6 + currentHash = manager.WriteInputAndCollectAndReturnHash(left, right) - temp8 := new(big.Int).Mul(temp2, temp7) // temp8 = temp2 * temp7 + index = api.Div(index, 2) + } - p_tmp.Add(p_tmp, temp8) - p_tmp.Mod(p_tmp, MOD) + api.AssertIsEqual(currentHash, circuit.RootHash) + } - // p_3 += (e[j+offset] - e[j]) * (a_z[j+offset] - a_z[j]) * (b_z[j+offset] - b_z[j]) - temp9 := new(big.Int).Sub(e[j+offset], e[j]) // temp9 = e[j+offset] - e[j] - temp10 := new(big.Int).Sub(a_z[j+offset], a_z[j]) // temp10 = a_z[j+offset] - a_z[j] - temp11 := new(big.Int).Sub(b_z[j+offset], b_z[j]) // temp11 = b_z[j+offset] - b_z[j] + return nil +} - temp12 := new(big.Int).Mul(temp9, temp10) - temp12.Mul(temp12, temp11) +func main() { + var number_of_variables = 2 - p_3.Add(p_3, temp12) - p_3.Mod(p_3, MOD) - } + var authPaths = make([][]frontend.Variable, number_of_variables) + for i := 0; i < number_of_variables; i++ { + authPaths[i] = make([]frontend.Variable, 3) + } - // p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 - temp13 := new(big.Int).Add(expected_sum, p_tmp) - temp13.Sub(temp13, p_0) - temp13.Sub(temp13, p_0) - temp13.Sub(temp13, p_0) - - p_2 := new(big.Int).Div(temp13, big.NewInt(2)) - p_2.Mod(p_2, MOD) - // p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 - p_1 := new(big.Int).Sub(expected_sum, p_0) - p_1.Sub(p_1, p_0) - p_1.Sub(p_1, p_3) - p_1.Sub(p_1, p_2) - p_1.Mod(p_1, MOD) - - coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2, p_3} - hash_value, _ := poseidon.Hash([]*big.Int{p_0, p_1, p_2, p_3}) - // Generate a random *big.Int less than 11 - r := hash_value - fmt.Println("r_", i, " = ", r) - challenge_vector = append(challenge_vector, r) - - e = replace_r_in_f(e, r) - a_z = replace_r_in_f(a_z, r) - b_z = replace_r_in_f(b_z, r) - c_z = replace_r_in_f(c_z, r) - - // expected_sum = p_0 + r*(p_1 + r*(p_2 + r*p_3)) - temp14 := new(big.Int).Mul(r, p_3) // r * p_3 - temp14.Add(temp14, p_2) // p_2 + r * p_3 - temp14.Mul(temp14, r) // r * (p_2 + r * p_3) - temp14.Add(temp14, p_1) // p_1 + r * (p_2 + r * p_3) - temp14.Mul(temp14, r) // r * (p_1 + r * (p_2 + r * p_3)) - expected_sum = new(big.Int).Add(p_0, temp14) - expected_sum.Mod(expected_sum, MOD) + var leaves = make([]frontend.Variable, 3) + var leaf_indexes = make([]frontend.Variable, 3) + var leaf_sibling_hashes = make([]frontend.Variable, 3) + var root_hash = big.NewInt(1) + + var circuit = VerifyMerkleProofCircuit{ + Leaves: leaves, + LeafIndexes: leaf_indexes, + LeafSiblingHashes: leaf_sibling_hashes, + AuthPaths: authPaths, + RootHash: root_hash, } - assignment := Circuit{ - ExpectedSum: initial_expected_sum, - ValueAtChallengeVector: expected_sum, - GPolynomials: coeffs_univariate_polynomials, + ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + pk, vk, _ := groth16.Setup(ccs) + + assignment := VerifyMerkleProofCircuit{ + Leaves: leaves, + LeafIndexes: leaf_indexes, + LeafSiblingHashes: leaf_sibling_hashes, + AuthPaths: authPaths, + RootHash: root_hash, } witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) publicWitness, _ := witness.Public() proof, _ := groth16.Prove(ccs, pk, witness) groth16.Verify(proof, vk, publicWitness) - //END R1CS case } diff --git a/main_spartan.go b/main_spartan.go new file mode 100644 index 0000000..b357790 --- /dev/null +++ b/main_spartan.go @@ -0,0 +1,251 @@ +package main + +import ( + "fmt" + "math/big" + "tutorial/sumcheck-verifier-circuit/hashmanager" + + "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/iden3/go-iden3-crypto/poseidon" +) + +const NUMBER_OF_COEFFS_IN_LINEAR = 2 +const NUMBER_OF_COEFFS_IN_QUADRATIC = 3 +const NUMBER_OF_COEFFS_IN_CUBIC = 4 + +var MOD *big.Int +var ONE_HALF_CONSTANT *big.Int + +func Init_Spartan() { + var success bool + MOD, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) + ONE_HALF_CONSTANT, success = new(big.Int).SetString("10944121435919637611123202872628637544274182200208017171849102093287904247809", 10) + if !success { + fmt.Println("Error: Failed to set big.Int value") + } +} + +type Circuit struct { + // Alleged computed sum of all the evaluations + ExpectedSum frontend.Variable `gnark:"ExpectedSum"` + ValueAtChallengeVector frontend.Variable `gnark:"ValueAtChallengeVector"` + // Array of elements representing the values of p0, p1 in each of the rounds + GPolynomials [][]frontend.Variable `gnark:"GPolynomials"` +} + +func (circuit *Circuit) Define(api frontend.API) error { + var manager = hashmanager.NewHashManager(api) + g_length := len(circuit.GPolynomials) + e := circuit.ExpectedSum + for i := 0; i < g_length; i++ { + api.AssertIsEqual(len(circuit.GPolynomials[i]), NUMBER_OF_COEFFS_IN_CUBIC) + + // Equivalent constraint to the one below it, doesn't require GPoly[i][0] + // e = api.Add(api.Mul(ONE_HALF_CONSTANT, api.Add(e, api.Neg(circuit.GPolynomials[i][1]))), api.Mul(circuit.ChallengeVector[i], circuit.GPolynomials[i][1])) + api.Println(circuit.GPolynomials[i][0], circuit.GPolynomials[i][1]) + r_i := manager.WriteInputAndCollectAndReturnHash(circuit.GPolynomials[i]...) + api.Println(r_i) + cumulative := circuit.GPolynomials[i][NUMBER_OF_COEFFS_IN_CUBIC-1] + for j := NUMBER_OF_COEFFS_IN_CUBIC - 2; j >= 1; j-- { + cumulative = api.Add(circuit.GPolynomials[i][j], api.Mul(cumulative, r_i)) + } + e = api.Add(circuit.GPolynomials[i][0], api.Mul(cumulative, r_i)) + } + api.AssertIsEqual(e, circuit.ValueAtChallengeVector) + return nil +} + +func calculateCubic(e []*big.Int, a_z []*big.Int, b_z []*big.Int, c_z []*big.Int) *big.Int { + result := big.NewInt(0) + for i := 0; i < len(e); i++ { + tmp := new(big.Int).Mul(a_z[i], b_z[i]) + tmp.Sub(tmp, c_z[i]) + tmp.Mul(tmp, e[i]) + result.Add(result, tmp) + } + return result +} + +func replace_r_in_f(f []*big.Int, r *big.Int) []*big.Int { + n := len(f) / 2 + for i := 0; i < n; i++ { + diff := new(big.Int).Sub(f[n+i], f[i]) // diff = f[n+i] - f[i] + scaled := new(big.Int).Mul(r, diff) // scaled = r * diff + f[i].Add(f[i], scaled) // f[i] += scaled + } + return f[:n] +} + +func main_spartan() { + Init_Spartan() + + // START R1CS case + // Sum_x e(x) * (a(x) * b(x) - c(x)) + var number_of_variables = 2 + + // initialize coefficients + var coeffs_univariate_polynomials = make([][]frontend.Variable, number_of_variables) + for i := 0; i < number_of_variables; i++ { + coeffs_univariate_polynomials[i] = make([]frontend.Variable, NUMBER_OF_COEFFS_IN_CUBIC) + } + var circuit = Circuit{ + GPolynomials: coeffs_univariate_polynomials, + } + + ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + pk, vk, _ := groth16.Setup(ccs) + // proof for some random values of e, Az, Bz, Cz + // still to validate for real A,B,C and its witness vector + + // Commented out since VerifyR1CS() is not defined in the provided code + // VerifyR1CS() + + // Initialize arrays with *big.Int + var e = []*big.Int{ + big.NewInt(1), + big.NewInt(4), + big.NewInt(3), + big.NewInt(6), + big.NewInt(3), + big.NewInt(5), + big.NewInt(0), + big.NewInt(0), + } + + var a_z = []*big.Int{ + big.NewInt(3), + big.NewInt(9), + big.NewInt(30), + big.NewInt(25), + big.NewInt(5), + big.NewInt(25), + big.NewInt(0), + big.NewInt(0), + } + + var b_z = []*big.Int{ + big.NewInt(3), + big.NewInt(3), + big.NewInt(1), + big.NewInt(1), + big.NewInt(5), + big.NewInt(1), + big.NewInt(0), + big.NewInt(0), + } + + var c_z = []*big.Int{ + big.NewInt(9), + big.NewInt(27), + big.NewInt(30), + big.NewInt(25), + big.NewInt(25), + big.NewInt(25), + big.NewInt(0), + big.NewInt(0), + } + + var initial_expected_sum = calculateCubic(e, a_z, b_z, c_z) + var expected_sum = new(big.Int).Set(initial_expected_sum) + var challenge_vector []frontend.Variable + + fmt.Println("Initial Expected Sum:", expected_sum) + + for i := 0; i < number_of_variables; i++ { + p_0 := big.NewInt(0) + p_tmp := big.NewInt(0) + p_3 := big.NewInt(0) + offset := len(e) / 2 + for j := 0; j < len(e)/2; j++ { + // p_0 += e[j] * (a_z[j]*b_z[j] - c_z[j]) + temp1 := new(big.Int).Mul(a_z[j], b_z[j]) // a_z[j]*a_z[j] + temp1.Sub(temp1, c_z[j]) // temp1 = temp1 - c_z[j] + temp1.Mul(temp1, e[j]) // temp1 = e[j] * (a_z[j]*b_z[j] - c_z[j]) + p_0.Add(p_0, temp1) + p_0.Mod(temp1, MOD) + + // p_tmp += (2*e[j] - e[j+offset]) * ((2*a_z[j]-a_z[j+offset])*(2*b_z[j]-b_z[j+offset]) - (2*c_z[j] - c_z[j+offset])) + temp2 := new(big.Int).Mul(big.NewInt(2), e[j]) // 2*e[j] + temp2.Sub(temp2, e[j+offset]) // temp2 = (2*e[j] - e[j+offset]) + + temp3 := new(big.Int).Mul(big.NewInt(2), a_z[j]) // 2*a_z[j] + temp3.Sub(temp3, a_z[j+offset]) // temp3 = (2*a_z[j] - a_z[j+offset]) + + temp4 := new(big.Int).Mul(big.NewInt(2), b_z[j]) // 2*b_z[j] + temp4.Sub(temp4, b_z[j+offset]) // temp4 = (2*b_z[j] - b_z[j+offset]) + + temp5 := new(big.Int).Mul(temp3, temp4) // temp5 = temp3 * temp4 + + temp6 := new(big.Int).Mul(big.NewInt(2), c_z[j]) // 2*c_z[j] + temp6.Sub(temp6, c_z[j+offset]) // temp6 = (2*c_z[j] - c_z[j+offset]) + + temp7 := new(big.Int).Sub(temp5, temp6) // temp7 = temp5 - temp6 + + temp8 := new(big.Int).Mul(temp2, temp7) // temp8 = temp2 * temp7 + + p_tmp.Add(p_tmp, temp8) + p_tmp.Mod(p_tmp, MOD) + + // p_3 += (e[j+offset] - e[j]) * (a_z[j+offset] - a_z[j]) * (b_z[j+offset] - b_z[j]) + temp9 := new(big.Int).Sub(e[j+offset], e[j]) // temp9 = e[j+offset] - e[j] + temp10 := new(big.Int).Sub(a_z[j+offset], a_z[j]) // temp10 = a_z[j+offset] - a_z[j] + temp11 := new(big.Int).Sub(b_z[j+offset], b_z[j]) // temp11 = b_z[j+offset] - b_z[j] + + temp12 := new(big.Int).Mul(temp9, temp10) + temp12.Mul(temp12, temp11) + + p_3.Add(p_3, temp12) + p_3.Mod(p_3, MOD) + } + + // p_2 := (expected_sum + p_tmp - p_0 - p_0 - p_0) / 2 + temp13 := new(big.Int).Add(expected_sum, p_tmp) + temp13.Sub(temp13, p_0) + temp13.Sub(temp13, p_0) + temp13.Sub(temp13, p_0) + + p_2 := new(big.Int).Div(temp13, big.NewInt(2)) + p_2.Mod(p_2, MOD) + // p_1 := expected_sum - p_0 - p_0 - p_3 - p_2 + p_1 := new(big.Int).Sub(expected_sum, p_0) + p_1.Sub(p_1, p_0) + p_1.Sub(p_1, p_3) + p_1.Sub(p_1, p_2) + p_1.Mod(p_1, MOD) + + coeffs_univariate_polynomials[i] = []frontend.Variable{p_0, p_1, p_2, p_3} + hash_value, _ := poseidon.Hash([]*big.Int{p_0, p_1, p_2, p_3}) + // Generate a random *big.Int less than 11 + r := hash_value + fmt.Println("r_", i, " = ", r) + challenge_vector = append(challenge_vector, r) + + e = replace_r_in_f(e, r) + a_z = replace_r_in_f(a_z, r) + b_z = replace_r_in_f(b_z, r) + c_z = replace_r_in_f(c_z, r) + + // expected_sum = p_0 + r*(p_1 + r*(p_2 + r*p_3)) + temp14 := new(big.Int).Mul(r, p_3) // r * p_3 + temp14.Add(temp14, p_2) // p_2 + r * p_3 + temp14.Mul(temp14, r) // r * (p_2 + r * p_3) + temp14.Add(temp14, p_1) // p_1 + r * (p_2 + r * p_3) + temp14.Mul(temp14, r) // r * (p_1 + r * (p_2 + r * p_3)) + expected_sum = new(big.Int).Add(p_0, temp14) + expected_sum.Mod(expected_sum, MOD) + } + + assignment := Circuit{ + ExpectedSum: initial_expected_sum, + ValueAtChallengeVector: expected_sum, + GPolynomials: coeffs_univariate_polynomials, + } + witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + publicWitness, _ := witness.Public() + proof, _ := groth16.Prove(ccs, pk, witness) + groth16.Verify(proof, vk, publicWitness) + //END R1CS case +} diff --git a/verify_merkle.go b/verify_merkle.go index 7df52a2..6cc180b 100644 --- a/verify_merkle.go +++ b/verify_merkle.go @@ -1,78 +1,32 @@ package main import ( - "math/big" "tutorial/sumcheck-verifier-circuit/hashmanager" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/std/math/cmp" ) -type VerifyMerkleProofCircuit struct { +type VerifyMerkleProofCircuit2 struct { // Inputs - Leaves []frontend.Variable - LeafIndexes []frontend.Variable - LeafSiblingHashes []frontend.Variable - AuthPathPrefixLenghts []frontend.Variable - AuthPathSuffixes [][]frontend.Variable //in Incremental Encoding + Leaves []frontend.Variable + LeafIndexes []frontend.Variable + LeafSiblingHashes []frontend.Variable + AuthPaths [][]frontend.Variable // Public Input RootHash frontend.Variable `gnark:",public"` } -func DecodePrefixPath(api frontend.API, circuitPrevPath []frontend.Variable, circuitPrefixLen frontend.Variable, circuitSuffix []frontend.Variable) []frontend.Variable { - const maxPrevPathLen = 20 - const maxSuffixLen = 20 - comparator := cmp.NewBoundedComparator(api, big.NewInt(1<<32-1), false) - - const resultLen = maxPrevPathLen + maxSuffixLen - - prevPath := make([]frontend.Variable, maxPrevPathLen) - suffix := make([]frontend.Variable, maxSuffixLen) - result := make([]frontend.Variable, resultLen) - - for i := 0; i < maxPrevPathLen; i++ { - prevPath[i] = circuitPrevPath[i] - } - for i := 0; i < maxSuffixLen; i++ { - suffix[i] = circuitSuffix[i] - } - - for i := 0; i < resultLen; i++ { - iVar, _ := api.ConstantValue(uint64(i)) - - isLessThanPrefixLen := comparator.IsLess(iVar, circuitPrefixLen) - indexInSuffix := api.Sub(iVar, circuitPrefixLen) - isInSuffixRange := comparator.IsLess(indexInSuffix, maxSuffixLen) - - prevPathElement := api.Select(isLessThanPrefixLen, prevPath[i], frontend.Variable(0)) - suffixElement := api.Select(isInSuffixRange, suffix[indexInSuffix], frontend.Variable(0)) - - result[i] = api.Add(prevPathElement, suffixElement) - } - - return result -} - -func (circuit *VerifyMerkleProofCircuit) Define(api frontend.API) error { - const N = 100 - +func (circuit *VerifyMerkleProofCircuit) Define2(api frontend.API) error { var manager = hashmanager.NewHashManager(api) numLeaves := len(circuit.Leaves) // ``treeHeight := len(circuit.AuthPathSuffixes[0]) + 2 - prevPath := circuit.AuthPathSuffixes[0] for i := 0; i < numLeaves; i++ { leaf := circuit.Leaves[i] leafIndex := circuit.LeafIndexes[i] leafSiblingHash := circuit.LeafSiblingHashes[i] - // DecodePrefixPath(api) - authPath := prevPath - if circuit.AuthPathPrefixLenghts[i] == 0 { - authPath = circuit.AuthPathSuffixes[i] - } else { - - } + authPath := circuit.AuthPaths[i] claimedLeafHash := manager.WriteInputAndCollectAndReturnHash(leaf)