From 976c8bb215a3f0b21ce3d05f894eb506072a6285 Mon Sep 17 00:00:00 2001 From: Agnish Ghosh <80243668+agnxsh@users.noreply.github.com> Date: Sat, 9 Mar 2024 10:28:29 +0530 Subject: [PATCH] Verkle IPA: Backend maintenance and further testing (#364) * added tests, some fixes * rm bin * added tests, some fixes * rm bin * changes * add: added recursive divide and conquer with (mostly) Views * rm: prev loop code * fix: checkIPAProof order * small fix * rm binary, cleanup leftovers * ipa fixes with divide and conquer * fix: upstreamed transcript fixed indent * rm: generateChallengeScalar from Upstream * rm: transcript from Upstream * transcript upstream * rm bin * add: types recognizable from nim-eth-verkle --- .../eth_verkle_ipa/barycentric_form.nim | 29 +- constantine/eth_verkle_ipa/common_utils.nim | 72 +++- .../eth_verkle_ipa/eth_verkle_constants.nim | 8 +- constantine/eth_verkle_ipa/ipa_prover.nim | 197 ++++++----- constantine/eth_verkle_ipa/ipa_verifier.nim | 23 +- constantine/eth_verkle_ipa/multiproof.nim | 251 +++++++------- constantine/eth_verkle_ipa/transcript_gen.nim | 6 +- constantine/ethereum_verkle_trees.nim | 101 +++--- .../serialization/codecs_banderwagon.nim | 2 - research/kzg/strided_views.nim | 3 + tests/t_ethereum_verkle_ipa_primitives.nim | 319 ++++++++++++++---- tests/t_ethereum_verkle_ipa_test_helper.nim | 74 ++-- 12 files changed, 673 insertions(+), 412 deletions(-) diff --git a/constantine/eth_verkle_ipa/barycentric_form.nim b/constantine/eth_verkle_ipa/barycentric_form.nim index d403e349..0258624e 100644 --- a/constantine/eth_verkle_ipa/barycentric_form.nim +++ b/constantine/eth_verkle_ipa/barycentric_form.nim @@ -115,7 +115,7 @@ func computeBarycentricCoefficients*(res_inv: var openArray[Fr[Banderwagon]], pr func getInvertedElement*(res: var Fr[Banderwagon], precomp : PrecomputedWeights, element : int, is_negative: bool) = var index: int - index = element - 1 + index = element - 1 if is_negative: var midpoint = precomp.invertedDomain.len div 2 @@ -136,30 +136,30 @@ func getBarycentricInverseWeight*(res: var Fr[Banderwagon], precomp: Precomputed func absIntChecker*[int] (res: var int, x : int) = - var is_negative {.noInit.}: bool + var is_negative = false if x < 0: is_negative = true - - if is_negative == true: - res = - x + if is_negative == true: + res = -x else: - res = x + res = x -func divisionOnDomain*(res: var array[VerkleDomain,Fr[Banderwagon]], precomp: PrecomputedWeights, index: var int, f: openArray[Fr[Banderwagon]]) = +func divisionOnDomain*(res: var array[VerkleDomain,Fr[Banderwagon]], precomp: PrecomputedWeights, index: var uint8, f: openArray[Fr[Banderwagon]]) = ## Computes f(x) - f(x_i) / x - x_i using the barycentric weights, where x_i is an element in the var is_negative = true + let index = int(index) var y = f[index] for i in 0 ..< VerkleDomain: - if i != index: - var denominator = i - index + if i != int(index): + + var denominator = i - int(index) var absDenominator {.noInit.}: int absDenominator.absIntChecker(denominator) - if absDenominator > 0: - is_negative = false - + doAssert absDenominator > 0, "Absolute Denominator should be greater than 0!" + is_negative = false var denominatorInv {.noInit.}: Fr[Banderwagon] denominatorInv.getInvertedElement(precomp, absDenominator, is_negative) @@ -170,9 +170,10 @@ func divisionOnDomain*(res: var array[VerkleDomain,Fr[Banderwagon]], precomp: Pr var weight_ratios {.noInit.}: Fr[Banderwagon] var dummy {.noInit.} : int dummy = i - weight_ratios.getWeightRatios(precomp, index, dummy) + var dummy2 = int(index) + weight_ratios.getWeightRatios(precomp, dummy2, dummy) var tmp {.noInit.}: Fr[Banderwagon] tmp.prod(weight_ratios, res[i]) + res[int(index)] -= tmp - res[index] -= tmp diff --git a/constantine/eth_verkle_ipa/common_utils.nim b/constantine/eth_verkle_ipa/common_utils.nim index 46853a7f..1ec31586 100644 --- a/constantine/eth_verkle_ipa/common_utils.nim +++ b/constantine/eth_verkle_ipa/common_utils.nim @@ -9,7 +9,7 @@ ## IPAConfiguration contains all of the necessary information to create Pedersen + IPA proofs ## such as the SRS import - ./[eth_verkle_constants], + ./[eth_verkle_constants, barycentric_form], ../platforms/primitives, ../math/config/[type_ff, curves], ../math/elliptic/ec_twistededwards_projective, @@ -17,7 +17,8 @@ import ../math/arithmetic, ../math/elliptic/ec_scalar_mul, ../math/elliptic/[ec_multi_scalar_mul, ec_multi_scalar_mul_scheduler], - ../platforms/[bithacks,views], + ../platforms/[bithacks], + ../../research/kzg/strided_views, ../curves_primitives, ../math/io/[io_bigints, io_fields], ../serialization/[codecs_banderwagon,codecs_status_codes, endians] @@ -29,13 +30,13 @@ import # ############################################################ -func generate_random_points* [EC_P](points: var openArray[EC_P], ipaTranscript: var IpaTranscript, num_points: uint64) = +func generate_random_points* [EC_P](points: var openArray[EC_P], num_points: uint64) = ## generate_random_points generates random points on the curve with the hardcoded VerkleSeed var points_found : seq[EC_P] var incrementer : uint64 = 0 var idx: int = 0 while true: - var ctx : sha256 + var ctx {.noInit.}: sha256 ctx.init() ctx.update(VerkleSeed) ctx.update(incrementer.toBytes(bigEndian)) @@ -75,7 +76,7 @@ func computeInnerProducts* [Fr] (res: var Fr, a,b : openArray[Fr])= for i in 0 ..< b.len: var tmp : Fr tmp.prod(a[i], b[i]) - res.sum(res,tmp) + res += tmp func computeInnerProducts* [Fr] (res: var Fr, a,b : View[Fr])= debug: doAssert (a.len == b.len).bool() == true, "Scalar lengths don't match!" @@ -91,25 +92,26 @@ func computeInnerProducts* [Fr] (res: var Fr, a,b : View[Fr])= # # ############################################################ -func foldScalars* [Fr] (res: var openArray[Fr], a,b : openArray[Fr], x: Fr)= +func foldScalars*(res: var openArray[Fr[Banderwagon]], a,b : View[Fr[Banderwagon]], x: Fr[Banderwagon])= ## Computes res[i] = a[i] + b[i] * x - debug: doAssert a.len == b.len , "Lengths should be equal!" + doAssert a.len == b.len , "Lengths should be equal!" for i in 0 ..< a.len: - var bx {.noInit.}: Fr - bx.prod(x, b[i]) - res[i].sum(bx, a[i]) + var bx {.noInit.}: Fr[Banderwagon] + bx.prod(b[i], x) + res[i].sum(a[i], bx) -func foldPoints* [EC_P] (res: var openArray[EC_P], a,b : var openArray[EC_P], x: Fr)= +func foldPoints*(res: var openArray[EC_P], a,b : View[EC_P], x: Fr[Banderwagon])= ## Computes res[i] = a[i] + b[i] * x - debug: doAssert a.len == b.len , "Should have equal lengths!" + doAssert a.len == b.len , "Should have equal lengths!" for i in 0 ..< a.len: var bx {.noInit.}: EC_P - - b[i].scalarMul(x.toBig()) bx = b[i] - res[i].sum(bx, a[i]) + var x_big {.noInit.}: matchingOrderBigInt(Banderwagon) + x_big.fromField(x) + bx.scalarMul(x_big) + res[i].sum(a[i],bx) func computeNumRounds*(res: var uint32, vectorSize: SomeUnsignedInt)= @@ -117,7 +119,7 @@ func computeNumRounds*(res: var uint32, vectorSize: SomeUnsignedInt)= ## An additional checker is added because we also do not allow for vectors whose size is a power of 2. debug: doAssert (vectorSize == uint64(0)).bool() == false, "Zero is not a valid input!" - var isP2 : bool = isPowerOf2_vartime(vectorSize) + let isP2 = isPowerOf2_vartime(vectorSize) debug: doAssert isP2 == true, "not a power of 2, hence not a valid inputs" @@ -143,5 +145,41 @@ func pedersen_commit_varbasis*[EC_P] (res: var EC_P, groupPoints: openArray[EC_P for i in 0 ..< g: groupPoints_aff[i].affine(groupPoints[i]) - res.multiScalarMul_reference_vartime(poly_big,groupPoints) + res.multiScalarMul_reference_vartime(poly_big, groupPoints_aff) + +func evalOutsideDomain* [Fr] (res: var Fr, precomp: PrecomputedWeights, f: openArray[Fr], point: Fr)= +# Evaluating the point z outside of VerkleDomain, here the VerkleDomain is 0-256, whereas the FieldSize is +# everywhere outside of it which is upto a 253 bit number, or 2²⁵³. + var pointMinusDomain: array[VerkleDomain, Fr] + var pointMinusDomain_inv: array[VerkleDomain, Fr] + for i in 0 ..< VerkleDomain: + var i_fr {.noInit.}: Fr + i_fr.fromInt(i) + + pointMinusDomain[i].diff(point, i_fr) + pointMinusDomain_inv[i].inv(pointMinusDomain[i]) + + var summand: Fr + summand.setZero() + + for x_i in 0 ..< pointMinusDomain_inv.len: + var weight: Fr + weight.getBarycentricInverseWeight(precomp, x_i) + var term: Fr + term.prod(weight, f[x_i]) + term *= pointMinusDomain_inv[x_i] + + summand.sum(summand,term) + + res.setOne() + + for i in 0 ..< VerkleDomain: + var i_fr: Fr + i_fr.fromInt(i) + + var tmp: Fr + tmp.diff(point, i_fr) + res *= tmp + + res *= summand \ No newline at end of file diff --git a/constantine/eth_verkle_ipa/eth_verkle_constants.nim b/constantine/eth_verkle_ipa/eth_verkle_constants.nim index 0bb0f305..3aa013e9 100644 --- a/constantine/eth_verkle_ipa/eth_verkle_constants.nim +++ b/constantine/eth_verkle_ipa/eth_verkle_constants.nim @@ -25,6 +25,12 @@ type EC_P* = ECP_TwEdwards_Prj[Fp[Banderwagon]] EC_P_Aff* = ECP_TwEdwards_Aff[Fp[Banderwagon]] +type Bytes* = array[32, byte] + +type + Point* = EC_P + Field* = Fr[Banderwagon] + type IPAProof* = object L_vector*: array[8,EC_P] @@ -57,8 +63,6 @@ type const VerkleSeed* = asBytes"eth_verkle_oct_2021" -type Bytes* = array[32, byte] - type IpaTranscript* [H: CryptoHash, N: static int] = object ctx*: H label*: array[N, byte] diff --git a/constantine/eth_verkle_ipa/ipa_prover.nim b/constantine/eth_verkle_ipa/ipa_prover.nim index 27f13221..525dadac 100644 --- a/constantine/eth_verkle_ipa/ipa_prover.nim +++ b/constantine/eth_verkle_ipa/ipa_prover.nim @@ -23,8 +23,10 @@ import ../math/config/[type_ff, curves], ../math/elliptic/[ec_twistededwards_projective], ../math/arithmetic, + ../math/io/io_fields, ../math/elliptic/ec_scalar_mul, - ../platforms/[views], + ../../research/kzg/strided_views, + # ../platforms/[views], ../curves_primitives # ############################################################ @@ -38,7 +40,7 @@ import # Further reference refer to this https://dankradfeist.de/ethereum/2021/07/27/inner-product-arguments.html -func genIPAConfig*(res: var IPASettings, ipaTranscript: var IpaTranscript[CryptoHash, 32]) : bool {.inline.} = +func genIPAConfig*(res: var IPASettings) : bool {.inline.} = # Initiates a new IPASettings # IPASettings has all the necessary information related to create an IPA proof # such as SRS, precomputed weights for Barycentric formula @@ -48,120 +50,140 @@ func genIPAConfig*(res: var IPASettings, ipaTranscript: var IpaTranscript[Crypto # genIPAConfig( ) generates the SRS, Q and the precomputed weights for barycentric formula. The SRS is generated # as random points of the VerkleDomain where the relative discrete log is unknown between each generator. - res.SRS.generate_random_points(ipaTranscript, uint64(VerkleDomain)) - res.Q_val.fromAffine(Banderwagon.getGenerator()) - res.precompWeights.newPrecomputedWeights() - res.numRounds.computeNumRounds(uint64(VerkleDomain)) - return true - -func createIPAProof*[IPAProof] (res: var IPAProof, transcript: var CryptoHash, ic: IPASettings, commitment: EC_P, a: var openArray[Fr[Banderwagon]], evalPoint: Fr[Banderwagon]) : bool {.inline.} = - ## createIPAProof creates an IPA proof for a committed polynomial in evaluation form. - ## `a` vectors are the evaluation points in the domain, and `evalPoint` represents the evaluation point. - transcript.domain_separator(asBytes"ipa") - var b {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] - - b.computeBarycentricCoefficients(ic.precompWeights, evalPoint) - var innerProd {.noInit.}: Fr[Banderwagon] - - innerProd.computeInnerProducts(a, b) + var random_points: array[VerkleDomain, EC_P] + random_points.generate_random_points(uint64(VerkleDomain)) + var q_val {.noInit.}: EC_P + q_val.fromAffine(Banderwagon.getGenerator()) + var precomp {.noInit.}: PrecomputedWeights + precomp.newPrecomputedWeights() + var nr: uint32 + nr.computeNumRounds(uint64(VerkleDomain)) + + res.numRounds = nr + res.Q_val = q_val + res.precompWeights = precomp + res.SRS = random_points - transcript.pointAppend(asBytes"C", commitment) - transcript.scalarAppend(asBytes"input point", evalPoint.toBig()) - transcript.scalarAppend(asBytes"output point", innerProd.toBig()) + return true - var w : matchingOrderBigInt(Banderwagon) - w.generateChallengeScalar(transcript, asBytes"w") +func populateCoefficientVector* (res: var openArray[Fr[Banderwagon]], ic: IPASettings, point: Fr[Banderwagon])= + var maxEvalPointInDomain {.noInit.}: Fr[Banderwagon] + maxEvalPointInDomain.fromInt(VerkleDomain - 1) - var q {.noInit.} : EC_P - q = ic.Q_val - q.scalarMul(w) + for i in 0 ..< res.len: + res[i].setZero() - var current_basis {.noInit.}: array[VerkleDomain, EC_P] - current_basis = ic.SRS + if (maxEvalPointInDomain.toBig() < point.toBig()).bool == false: + let p = cast[int](point.toBig()) + res[p].setOne() - var num_rounds = ic.numRounds + else: + res.computeBarycentricCoefficients(ic.precompWeights, point) - var L {.noInit.}: array[8, EC_P] - var R {.noInit.}: array[8, EC_P] +func coverIPARounds*(res: var IPAProof, transcript: var CryptoHash, ic: IPASettings, a: var openArray[Fr[Banderwagon]], b: var openArray[Fr[Banderwagon]], cb_c: var openArray[EC_P], q: EC_P, idx, rounds: var int): bool = var a_view = a.toView() var b_view = b.toView() - var current_basis_view = current_basis.toView() + var cur_view = cb_c.toView() - for i in 0 ..< int(num_rounds): - var a_L = a_view.chunk(0, a_view.len shr 1) - var a_R = a_view.chunk(a_view.len shr 1 + 1, a_view.len) + var (a_L, a_R) = a_view.splitMiddle() + var (b_L, b_R) = b_view.splitMiddle() + var (G_L, G_R) = cur_view.splitMiddle() - var b_L = b_view.chunk(0, b_view.len shr 1) - var b_R = b_view.chunk(b_view.len shr 1 + 1, b_view.len) + var z_L {.noInit.}: Fr[Banderwagon] + z_L.computeInnerProducts(a_R.toOpenArray(), b_L.toOpenArray()) - var G_L = current_basis_view.chunk(0, current_basis_view.len shr 1) - var G_R = current_basis_view.chunk(current_basis_view.len shr 1 + 1, current_basis_view.len) + var z_R {.noInit.}: Fr[Banderwagon] + z_R.computeInnerProducts(a_L.toOpenArray(), b_R.toOpenArray()) - var z_L {.noInit.}: Fr[Banderwagon] - z_L.computeInnerProducts(a_R, b_L) + var C_L {.noInit.}: EC_P + C_L = q + C_L.scalarMul(z_L.toBig()) - var z_R {.noInit.}: Fr[Banderwagon] - z_R.computeInnerProducts(a_L, b_R) - var one : Fr[Banderwagon] - one.setOne() + var C_L_1 {.noInit.}: EC_P + C_L_1.x.setZero() + C_L_1.y.setZero() + C_L_1.z.setOne() + C_L_1.pedersen_commit_varbasis(G_L.toOpenArray(), G_L.len, a_R.toOpenArray(), a_R.len) + C_L += C_L_1 - var C_L_1 {.noInit.}: EC_P - C_L_1.pedersen_commit_varbasis(G_L.toOpenArray(), G_L.toOpenArray().len, a_R.toOpenArray(), a_R.len) + var C_R {.noInit.}: EC_P + C_R = q + C_R.scalarMul(z_R.toBig()) + + var C_R_1 {.noInit.}: EC_P + C_R_1.x.setZero() + C_R_1.y.setZero() + C_R_1.z.setOne() + C_R_1.pedersen_commit_varbasis(G_R.toOpenArray(), G_R.len, a_L.toOpenArray(), a_L.len) + C_R += C_R_1 - var fp1 : array[2, EC_P] - fp1[0] = C_L_1 - fp1[1] = q + res.L_vector[idx] = C_L + res.R_vector[idx] = C_R + idx = idx + 1 - var fr1 : array[2, Fr[Banderwagon]] - fr1[0] = one - fr1[1] = z_L + transcript.pointAppend(asBytes"L", C_L) + transcript.pointAppend(asBytes"R", C_R) - var C_L {.noInit.}: EC_P - C_L.pedersen_commit_varbasis(fp1, fp1.len, fr1, fr1.len) + var x_big: matchingOrderBigInt(Banderwagon) + x_big.generateChallengeScalar(transcript, asBytes"x") - var C_R_1 {.noInit.}: EC_P - C_R_1.pedersen_commit_varbasis(G_R.toOpenArray(), G_R.toOpenArray().len, a_L.toOpenArray(), a_L.len) + var x {.noInit.}: Fr[Banderwagon] + x.fromBig(x_big) - var C_R {.noInit.}: EC_P + var xInv {.noInit.}: Fr[Banderwagon] + xInv.inv(x) - var fp2 : array[2, EC_P] - fp2[0] = C_R_1 - fp2[1] = q + var ai, bi = newSeq[Fr[Banderwagon]](a_L.len) + var gi = newSeq[EC_P](a_L.len) - var fr2: array[2, Fr[Banderwagon]] - fr2[0] = one - fr2[1] = z_R + ai.foldScalars(a_L, a_R, x) + bi.foldScalars(b_L, b_R, xInv) + gi.foldPoints(G_L, G_R, xInv) - C_R.pedersen_commit_varbasis(fp2, fp2.len, fr2, fr2.len) + res.A_scalar = a_L[0] - L[i] = C_L - R[i] = C_R + if idx == 7: + return true - transcript.pointAppend(asBytes"L", C_L) - transcript.pointAppend(asBytes"R", C_R) + coverIPARounds(res, transcript, ic, ai, bi, gi, q, idx, rounds) - var x_big: matchingOrderBigInt(Banderwagon) - x_big.generateChallengeScalar(transcript, asBytes"x") - var x: Fr[Banderwagon] - x.fromBig(x_big) +func createIPAProof*[IPAProof] (res: var IPAProof, transcript: var CryptoHash, ic: IPASettings, commitment: EC_P, a: var openArray[Fr[Banderwagon]], evalPoint: Fr[Banderwagon]) : bool = + ## createIPAProof creates an IPA proof for a committed polynomial in evaluation form. + ## `a` vectors are the evaluation points in the domain, and `evalPoint` represents the evaluation point. + transcript.domain_separator(asBytes"ipa") + var b: array[VerkleDomain, Fr[Banderwagon]] + b.populateCoefficientVector(ic, evalPoint) + + var innerProd {.noInit.}: Fr[Banderwagon] + innerProd.computeInnerProducts(a, b) - var xInv: Fr[Banderwagon] - xInv.inv(x) + transcript.pointAppend(asBytes"C", commitment) + transcript.scalarAppend(asBytes"input point", evalPoint.toBig()) + transcript.scalarAppend(asBytes"output point", innerProd.toBig()) - a.foldScalars(a_L.toOpenArray(), a_R.toOpenArray(), x) + var w {.noInit.}: matchingOrderBigInt(Banderwagon) + w.generateChallengeScalar(transcript, asBytes"w") + + var w_fr {.noInit.}: Fr[Banderwagon] + w_fr.fromBig(w) + + var q {.noInit.}: EC_P + q = ic.Q_val + q.scalarMul(w) - b.foldScalars(b_L.toOpenArray(), b_R.toOpenArray(), xInv) + var cb_c: array[VerkleDomain, EC_P] + for i in 0 ..< VerkleDomain: + cb_c[i] = ic.SRS[i] - current_basis.foldPoints(G_L.toOpenArray(), G_R.toOpenArray(), xInv) + var idx = 0 + var num_rounds = 8 + # 0-indexed - debug: doAssert not(a.len == 1), "Length of `a` should be 1 at the end of the reduction" + discard coverIPARounds(res, transcript, ic, a, b, cb_c, q, idx, num_rounds) - res.L_vector = L - res.R_vector = R - res.A_scalar = a[0] return true # ############################################################ @@ -191,8 +213,7 @@ func serializeVerkleIPAProof* (dst: var VerkleIPAProofSerialized, src: IPAProof) let stat1 = L_bytes.serializeBatch(src.L_vector) doAssert stat1 == cttCodecEcc_Success, "Batch serialization Failure!" - - + let stat2 = R_bytes.serializeBatch(src.R_vector) doAssert stat2 == cttCodecEcc_Success, "Batch Serialization Failure!" @@ -200,7 +221,7 @@ func serializeVerkleIPAProof* (dst: var VerkleIPAProofSerialized, src: IPAProof) let stat3 = A_bytes.serialize_scalar(src.A_scalar.toBig(), littleEndian) doAssert stat3 == cttCodecScalar_Success, "Scalar Serialization Failure!" - var idx : int = 0 + var idx: int = 0 for i in 0 ..< 8: for j in 0 ..< 32: @@ -275,8 +296,7 @@ func deserializeVerkleIPAProof* (dst: var IPAProof, src: var VerkleIPAProofSeria var i : int = 0 for item in L_bytes.items(): - let stat = L_side[i].deserialize(item) - doAssert stat == cttCodecEcc_Success, "Deserialization failure!" + discard L_side[i].deserialize(item) i = i + 1 discard L_bytes @@ -285,8 +305,7 @@ func deserializeVerkleIPAProof* (dst: var IPAProof, src: var VerkleIPAProofSeria i = 0 for item in R_bytes.items(): - let stat = R_side[i].deserialize(item) - doAssert stat == cttCodecEcc_Success, "Deserialization failure!" + discard R_side[i].deserialize(item) i = i + 1 discard R_bytes diff --git a/constantine/eth_verkle_ipa/ipa_verifier.nim b/constantine/eth_verkle_ipa/ipa_verifier.nim index 429261a0..84d1c094 100644 --- a/constantine/eth_verkle_ipa/ipa_verifier.nim +++ b/constantine/eth_verkle_ipa/ipa_verifier.nim @@ -7,7 +7,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - ./[transcript_gen, common_utils, barycentric_form, eth_verkle_constants], + ./[transcript_gen, common_utils, barycentric_form, eth_verkle_constants, ipa_prover], ../platforms/primitives, ../math/config/[type_ff, curves], ../hashes, @@ -30,7 +30,7 @@ func generateChallengesForIPA*(res: var openArray[matchingOrderBigInt(Banderwago transcript.pointAppend( asBytes"R", proof.R_vector[i]) res[i].generateChallengeScalar(transcript,asBytes"x") -func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: var EC_P, proof: IPAProof, evalPoint: Fr[Banderwagon], res: Fr[Banderwagon]) : bool = +func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, got: var EC_P, commitment: var EC_P, proof: IPAProof, evalPoint: Fr[Banderwagon], res: Fr[Banderwagon]) : bool = # Check IPA proof verifier a IPA proof for a committed polynomial in evaluation form # It verifies whether the proof is valid for the given polynomial at the evaluation `evalPoint` # and cross-checking it with `result` @@ -44,7 +44,8 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va var b {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] - b.computeBarycentricCoefficients(ic.precompWeights,evalPoint) + # b.computeBarycentricCoefficients(ic.precompWeights,evalPoint) + b.populateCoefficientVector(ic, evalPoint) transcript.pointAppend(asBytes"C", commitment) transcript.scalarAppend(asBytes"input point", evalPoint.toBig()) @@ -61,13 +62,13 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va var qy {.noInit.}: EC_P qy = q qy.scalarMul(res.toBig()) - commitment.sum(commitment, qy) + commitment += qy - var challenges_big: array[8, matchingOrderBigInt(Banderwagon)] + var challenges_big {.noInit.}: array[8, matchingOrderBigInt(Banderwagon)] challenges_big.generateChallengesForIPA(transcript, proof) - var challenges: array[8,Fr[Banderwagon]] + var challenges {.noInit.}: array[8,Fr[Banderwagon]] for i in 0 ..< 8: challenges[i].fromBig(challenges_big[i]) @@ -79,13 +80,13 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va var L = proof.L_vector[i] var R = proof.R_vector[i] - var p11: array[3, EC_P] + var p11 {.noInit.}: array[3, EC_P] p11[0] = commitment p11[1] = L p11[2] = R - var p22: array[3, Fr[Banderwagon]] - var one: Fr[Banderwagon] + var p22 {.noInit.}: array[3, Fr[Banderwagon]] + var one {.noInit.}: Fr[Banderwagon] one.setOne() p22[0] = one @@ -106,7 +107,7 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va for challengeIndex in 0 ..< challenges.len: let im = 1 shl (7 - challengeIndex) if ((i and im).int() > 0).bool() == true: - scalar.prod(scalar,challengesInv[challengeIndex]) + scalar *= challengesInv[challengeIndex] foldingScalars[i] = scalar @@ -127,7 +128,6 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va var b0 {.noInit.} : Fr[Banderwagon] b0.computeInnerProducts(b, foldingScalars) - var got {.noInit.} : EC_P # g0 * a + (a * b) * Q var p1 {.noInit.}: EC_P @@ -145,6 +145,7 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, commitment: va if not(got == commitment).bool() == true: r = false + return r r = true return r \ No newline at end of file diff --git a/constantine/eth_verkle_ipa/multiproof.nim b/constantine/eth_verkle_ipa/multiproof.nim index 931f2d00..4604741b 100644 --- a/constantine/eth_verkle_ipa/multiproof.nim +++ b/constantine/eth_verkle_ipa/multiproof.nim @@ -8,6 +8,7 @@ import tables, + sequtils, ./[transcript_gen, common_utils, ipa_prover, barycentric_form, eth_verkle_constants, ipa_verifier], ../platforms/primitives, ../hashes, @@ -31,15 +32,6 @@ import # ############################################################ -func domainToFrElem* (res: var Fr, inp: uint8)= - # The multiproof is a multi-proving system for several polynomials in the evaluation form - # Converts the const VERKLE_DOMAIN 256 to Fr[Banderwagon] - var x {.noInit.} : Fr - var x_big {.noInit.}: matchingOrderBigInt(Banderwagon) - x_big.fromUint(inp) - x.fromBig(x_big) - res = x - func domainToFrElem*(res: var Fr, inp: matchingOrderBigInt(Banderwagon))= var x {.noInit.} : Fr[Banderwagon] x.fromBig(inp) @@ -59,7 +51,7 @@ func computePowersOfElem*(res: var openArray[Fr], x: Fr, degree: SomeSignedInt)= # ############################################################ -func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var CryptoHash, ipaSetting: IPASettings, Cs: openArray[EC_P], Fs: array[VERKLE_DOMAIN, array[VERKLE_DOMAIN, Fr[Banderwagon]]], Zs: openArray[uint8], precomp: PrecomputedWeights, basis: array[VERKLE_DOMAIN, EC_P]) : bool = +func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var CryptoHash, ipaSetting: IPASettings, Cs: openArray[EC_P], Fs: array[VerkleDomain, array[VerkleDomain, Fr[Banderwagon]]], Zs: openArray[int]) : bool = # createMultiProof creates a multi-proof for several polynomials in the evaluation form # The list of triplets are as follows: (C, Fs, Z) represents each polynomial commitment # and their evaluation in the domain, and the evaluating point respectively @@ -67,31 +59,25 @@ func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var Crypto transcript.domain_separator(asBytes"multiproof") for f in Fs: - debug: debug: doAssert f.len == VERKLE_DOMAIN, "Polynomial length does not match with the VERKLE_DOMAIN length!" + debug: doAssert f.len == VerkleDomain, "Polynomial length does not match with the VerkleDomain length!" - debug: debug: doAssert Cs.len == Fs.len, "Number of commitments is NOT same as number of Functions" + debug: doAssert Cs.len == Fs.len, "Number of commitments is NOT same as number of Functions" - debug: debug: doAssert Cs.len == Zs.len, "Number of commitments is NOT same as the number of Points" + debug: doAssert Cs.len == Zs.len, "Number of commitments is NOT same as the number of Points" - var num_queries {.noInit.} : int + var num_queries {.noInit.}: int num_queries = Cs.len - var Cs_prime {.noInit.} : array[VERKLE_DOMAIN, EC_P] - for i in 0 ..< VERKLE_DOMAIN: - Cs_prime[i] = Cs[i] - for i in 0 ..< num_queries: - transcript.pointAppend(asBytes"C", Cs_prime[i]) - var z {.noInit.} : Fr[Banderwagon] - z.domainToFrElem(Zs[i]) + transcript.pointAppend(asBytes"C", Cs[i]) + var z {.noInit.}: Fr[Banderwagon] + z.fromInt(Zs[i]) transcript.scalarAppend(asBytes"z",z.toBig()) # deducing the `y` value var f = Fs[i] - - var y = f[int(Zs[i])] - + var y = f[Zs[i]] transcript.scalarAppend(asBytes"y", y.toBig()) var r {.noInit.} : matchingOrderBigInt(Banderwagon) @@ -100,49 +86,45 @@ func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var Crypto var r_fr {.noInit.}: Fr[Banderwagon] r_fr.fromBig(r) - var powersOfr {.noInit.}: array[VERKLE_DOMAIN,Fr[Banderwagon]] + var powersOfr {.noInit.} = newSeq[Fr[Banderwagon]](int(num_queries)) powersOfr.computePowersOfElem(r_fr, int(num_queries)) # In order to compute g(x), we first compute the polynomials in lagrange form grouped by evaluation points # then we compute g(x), this is eventually limit the numbers of divisionOnDomain calls up to the domain size - var groupedFs: array[VERKLE_DOMAIN, array[VERKLE_DOMAIN, Fr[Banderwagon]]] - # Initialize the array with zeros - for i in 0 ..< VERKLE_DOMAIN: - for j in 0 ..< VERKLE_DOMAIN: + var groupedFs: array[VerkleDomain, array[VerkleDomain, Fr[Banderwagon]]] + for i in 0 ..< VerkleDomain: + for j in 0 ..< VerkleDomain: groupedFs[i][j].setZero() - for i in 0 ..< num_queries: var z = Zs[i] - - debug: doAssert not(groupedFs[z].len == 0), "Length should not be 0!" - var r {.noInit.}: Fr[Banderwagon] r = powersOfr[i] - for j in 0 ..< VERKLE_DOMAIN: + for j in 0 ..< VerkleDomain: var scaledEvals {.noInit.}: Fr[Banderwagon] scaledEvals.prod(r, Fs[i][j]) - groupedFs[z][j].sum(groupedFs[z][j], scaledEvals) - - - var gx : array[VERKLE_DOMAIN, Fr[Banderwagon]] + groupedFs[z][j] += scaledEvals + + var gx {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + gx[i].setZero() - for idx in 0 ..< VERKLE_DOMAIN: - if groupedFs[idx].len == 0: + for i in 0 ..< VerkleDomain: + let check = groupedFs[i][0].isZero() + if check.bool() == true: continue - var quotient: array[VERKLE_DOMAIN,Fr[Banderwagon]] - var passer : int - passer = idx - quotient.divisionOnDomain(precomp, passer, groupedFs[idx]) - - for j in 0 ..< VERKLE_DOMAIN: - gx[j] += quotient[j] + var quotient {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + var passer = uint8(i) + quotient.divisionOnDomain(ipaSetting.precompWeights, passer, groupedFs[i]) - var D: EC_P - D.pedersen_commit_varbasis(basis,basis.len, gx, gx.len) + for j in 0 ..< VerkleDomain: + gx[j] += quotient[j] + + var D {.noInit.}: EC_P + D.pedersen_commit_varbasis(ipaSetting.SRS,ipaSetting.SRS.len, gx, gx.len) transcript.pointAppend(asBytes"D", D) @@ -153,62 +135,61 @@ func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var Crypto t_fr.fromBig(t) # Computing the denominator inverses only for referenced evaluation points. - var denInv {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] - for i in 0 ..< VERKLE_DOMAIN: - denInv[i].setZero() + var denInv {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] - for z in 0 ..< VERKLE_DOMAIN: - if groupedFs[z].len == 0: + var idxx = 0 + for i in 0 ..< VerkleDomain: + let check = groupedFs[i][0].isZero() + if check.bool() == true: continue - var z_fr {.noInit.} : Fr[Banderwagon] - z_fr.domainToFrElem(uint8(z)) + var z_fr {.noInit.}: Fr[Banderwagon] + z_fr.fromInt(i) var deno {.noInit.}: Fr[Banderwagon] - - deno.diff(t_fr,z_fr) - var idxx = 0 + deno.diff(t_fr, z_fr) + denInv[idxx] = deno idxx = idxx + 1 - var denInv_prime {.noInit.} : array[VERKLE_DOMAIN, Fr[Banderwagon]] + var denInv_prime {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] denInv_prime.batchInvert(denInv) #Compute h(X) = g1(X) - var hx {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] + var hx {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] var denInvIdx = 0 - for i in 0 ..< VERKLE_DOMAIN: - if groupedFs[i].len == 0: + for i in 0 ..< VerkleDomain: + let check = groupedFs[i][0].isZero() + if check.bool() == true: continue - for k in 0 ..< VERKLE_DOMAIN: + for k in 0 ..< VerkleDomain: var tmp {.noInit.}: Fr[Banderwagon] - tmp.prod(groupedFs[i][k], denInv[denInvIdx]) - hx[k].sum(hx[k], tmp) + tmp.prod(groupedFs[i][k], denInv_prime[denInvIdx]) + hx[k] += tmp denInvIdx = denInvIdx + 1 - var hMinusg {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] + var hMinusg {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] - for i in 0 ..< VERKLE_DOMAIN: + for i in 0 ..< VerkleDomain: hMinusg[i].diff(hx[i],gx[i]) - var E: EC_P + var E {.noInit.}: EC_P - E.pedersen_commit_varbasis(basis,basis.len, hx, hx.len) + E.pedersen_commit_varbasis(ipaSetting.SRS, ipaSetting.SRS.len, hx, hx.len) transcript.pointAppend(asBytes"E",E) - var EMinusD: EC_P - + var EMinusD {.noInit.}: EC_P EMinusD.diff(E,D) - var ipaProof: IPAProof + var ipaProof {.noInit.}: IPAProof var checks: bool checks = ipaProof.createIPAProof(transcript, ipaSetting, EMinusD, hMinusg, t_fr) - debug: doAssert checks == true, "Could not compute IPA Proof!" + doAssert checks == true, "Could not compute IPA Proof!" res.IPAprv = ipaProof res.D = D @@ -223,29 +204,23 @@ func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var Crypto # ############################################################ -func verifyMultiproof*(multiProof: var MultiProof, transcript : var CryptoHash, ipaSettings: IPASettings, Cs: openArray[EC_P], Ys: openArray[Fr[Banderwagon]], Zs: openArray[uint8]) : bool = +func verifyMultiproof*(multiProof: var MultiProof, transcript : var CryptoHash, ipaSettings: IPASettings, Cs: openArray[EC_P], Ys: openArray[Fr[Banderwagon]], Zs: openArray[int]) : bool = # Multiproof verifier verifies the multiproof for several polynomials in the evaluation form # The list of triplets (C,Y,Z) represents each polynomial commitment, evaluation # result, and evaluation point in the domain var res {.noInit.} : bool transcript.domain_separator(asBytes"multiproof") - debug: debug: doAssert Cs.len == Ys.len, "Number of commitments and the Number of output points don't match!" + debug: doAssert Cs.len == Ys.len, "Number of commitments and the Number of output points don't match!" - debug: debug: doAssert Cs.len == Zs.len, "Number of commitments and the Number of input points don't match!" + debug: doAssert Cs.len == Zs.len, "Number of commitments and the Number of input points don't match!" var num_queries = Cs.len - var checker {.noInit.}: bool - checker = num_queries == 0 - - debug: debug: doAssert num_queries == 0, "Number of queries is zero!" - for i in 0 ..< num_queries: transcript.pointAppend(asBytes"C", Cs[i]) - var z {.noInit.} : Fr[Banderwagon] - z.domainToFrElem(Zs[i]) + z.fromInt(Zs[i]) transcript.scalarAppend(asBytes"z", z.toBig()) transcript.scalarAppend(asBytes"y", Ys[i].toBig()) @@ -256,7 +231,7 @@ func verifyMultiproof*(multiProof: var MultiProof, transcript : var CryptoHash, var r_fr {.noInit.}: Fr[Banderwagon] r_fr.fromBig(r) - var powersOfr {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] + var powersOfr {.noInit.} = newSeq[Fr[Banderwagon]](int(num_queries)) powersOfr.computePowersOfElem(r_fr, int(num_queries)) transcript.pointAppend(asBytes"D", multiProof.D) @@ -265,81 +240,87 @@ func verifyMultiproof*(multiProof: var MultiProof, transcript : var CryptoHash, t.generateChallengeScalar(transcript, asBytes"t") var t_fr {.noInit.}: Fr[Banderwagon] - t_fr.fromBig(r) + t_fr.fromBig(t) # Computing the polynomials in the Lagrange form grouped by evaluation point, # and the needed helper scalars - var groupedEvals {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] + var groupedEvals {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + groupedEvals[i].setZero() for i in 0 ..< num_queries: - - var z {.noInit.}: uint8 - z = Zs[i] - + var z = Zs[i] var r {.noInit.} : Fr[Banderwagon] r = powersOfr[i] - var scaledEvals {.noInit.}: Fr[Banderwagon] scaledEvals.prod(r, Ys[i]) - groupedEvals[z].sum(groupedEvals[z], scaledEvals) - - #Calculating the helper scalar denominator, which is 1 / t - z_i - var helperScalarDeno {.noInit.} : array[VERKLE_DOMAIN, Fr[Banderwagon]] - - for i in 0 ..< VERKLE_DOMAIN: - var z {.noInit.}: Fr[Banderwagon] - z.domainToFrElem(uint8(i)) - - helperScalarDeno[i].diff(t_fr, z) + groupedEvals[z] += scaledEvals - var helperScalarDeno_prime: array[VERKLE_DOMAIN, Fr[Banderwagon]] - helperScalarDeno_prime.batchInvert(helperScalarDeno) + # Calculating the helper scalar denominator, which is 1 / t - z_i + var helperScalarDeno {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + helperScalarDeno[i].setZero() - # Compute g_2(t) = SUMMATION (y_i * r^i) / (t - z_i) = SUMMATION (y_i * r) * helperScalarDeno - var g2t {.noInit.} : Fr[Banderwagon] - g2t.setZero() + for i in 0 ..< VerkleDomain: + var z {.noInit.}: Fr[Banderwagon] + z.fromInt(i) + helperScalarDeno[i].diff(t_fr, z) - for i in 0 ..< VERKLE_DOMAIN: - var stat = groupedEvals[i].isZero() - if stat.bool() == true: - continue + var helperScalarDeno_prime {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + helperScalarDeno_prime.batchInvert(helperScalarDeno) - var tmp {.noInit.}: Fr[Banderwagon] - tmp.prod(groupedEvals[i], helperScalarDeno_prime[i]) - g2t += tmp + # Compute g_2(t) = SUMMATION (y_i * r^i) / (t - z_i) = SUMMATION (y_i * r) * helperScalarDeno + var g2t {.noInit.}: Fr[Banderwagon] - - # Compute E = SUMMATION C_i * (r^i / t - z_i) = SUMMATION C_i * MSM_SCALARS - var msmScalars {.noInit.}: array[VERKLE_DOMAIN, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + let stat = groupedEvals[i].isZero() + if stat.bool() == true: + continue - var Csnp {.noInit.}: array[VERKLE_DOMAIN, EC_P] + var tmp {.noInit.}: Fr[Banderwagon] + tmp.prod(groupedEvals[i], helperScalarDeno_prime[i]) + g2t += tmp - for i in 0 ..< VERKLE_DOMAIN: - Csnp[i] = Cs[i] - msmScalars[i].prod(powersOfr[i], helperScalarDeno_prime[Zs[i]]) - - var E {.noInit.}: EC_P + + # Compute E = SUMMATION C_i * (r^i / t - z_i) = SUMMATION C_i * MSM_SCALARS + var msmScalars {.noInit.}: array[VerkleDomain, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + msmScalars[i].setZero() + + var Csnp {.noInit.}: array[VerkleDomain, EC_P] + for i in 0 ..< VerkleDomain: + Csnp[i].setInf() + + for i in 0 ..< Cs.len: + Csnp[i] = Cs[i] + msmScalars[i].prod(powersOfr[i], helperScalarDeno_prime[Zs[i]]) + + var E {.noInit.}: EC_P - var Csnp_aff : array[VERKLE_DOMAIN, EC_P_Aff] - for i in 0 ..< VERKLE_DOMAIN: - Csnp_aff[i].affine(Csnp[i]) + var Csnp_aff {.noInit.}: array[VerkleDomain, EC_P_Aff] + for i in 0 ..< Cs.len: + Csnp_aff[i].affine(Csnp[i]) - var msmScalars_big: array[VERKLE_DOMAIN, matchingOrderBigInt(Banderwagon)] + var msmScalars_big {.noInit.}: array[VerkleDomain, matchingOrderBigInt(Banderwagon)] - for i in 0 ..< VERKLE_DOMAIN: - msmScalars_big[i] = msmScalars[i].toBig() - - E.multiScalarMul_reference_vartime(msmScalars_big, Csnp_aff) + for i in 0 ..< VerkleDomain: + msmScalars_big[i] = msmScalars[i].toBig() + + E.multiScalarMul_reference_vartime(msmScalars_big, Csnp_aff) - transcript.pointAppend(asBytes"E", E) + transcript.pointAppend(asBytes"E", E) - var EMinusD {.noInit.} : EC_P - EMinusD.diff(E, multiProof.D) + var EMinusD {.noInit.} : EC_P + EMinusD.diff(E, multiProof.D) - res = ipaSettings.checkIPAProof(transcript, EMinusD, multiProof.IPAprv, t_fr, g2t) + var got {.noInit.}: EC_P + res = ipaSettings.checkIPAProof(transcript, got, EMinusD, multiProof.IPAprv, t_fr, g2t) + if res == false: return res + return res + # ############################################################ # # Multiproof Serializer diff --git a/constantine/eth_verkle_ipa/transcript_gen.nim b/constantine/eth_verkle_ipa/transcript_gen.nim index b582eeef..5111cd17 100644 --- a/constantine/eth_verkle_ipa/transcript_gen.nim +++ b/constantine/eth_verkle_ipa/transcript_gen.nim @@ -58,7 +58,7 @@ func generateChallengeScalar*(challenge: var matchingOrderBigInt(Banderwagon), t # Generating Challenge Scalars based on the Fiat Shamir method transcript.domainSeparator(label) - var hash {.noInit.} : array[32, byte] + var hash {.noInit.}: array[32, byte] # Finalise the transcript state into a hash transcript.finish(hash) @@ -68,9 +68,9 @@ func generateChallengeScalar*(challenge: var matchingOrderBigInt(Banderwagon), t debug: doAssert stat, "transcript_gen.generateChallengeScalar: Unexpected failure" # Reset the Transcript state - transcript.clear() + transcript.init() challenge = interim_challenge.toBig() # Append the challenge into the resetted transcript transcript.scalarAppend(label, challenge) - \ No newline at end of file + \ No newline at end of file diff --git a/constantine/ethereum_verkle_trees.nim b/constantine/ethereum_verkle_trees.nim index e7b90de4..8db1b4a2 100644 --- a/constantine/ethereum_verkle_trees.nim +++ b/constantine/ethereum_verkle_trees.nim @@ -13,7 +13,8 @@ import common_utils, ipa_prover, ipa_verifier, - multiproof + multiproof, + transcript_gen ] # ############################################################ # @@ -24,65 +25,79 @@ import # Ethereum Verkle Constants # ------------------------------------------------------------ export - eth_verkle_constants.EC_P, - eth_verkle_constants.EC_P_Aff, - eth_verkle_constants.IPAProof, - eth_verkle_constants.MultiProof, - eth_verkle_constants.VerkleDomain, - eth_verkle_constants.PrecomputedWeights, - eth_verkle_constants.IPASettings, - eth_verkle_constants.VerkleSeed, - eth_verkle_constants.Bytes, - eth_verkle_constants.VerkleIPAProofSerialized, - eth_verkle_constants.VerkleMultiproofSerialized, - eth_verkle_constants.IpaTranscript, - eth_verkle_constants.Coord, - eth_verkle_constants.generator + eth_verkle_constants.EC_P, + eth_verkle_constants.Point, + eth_verkle_constants.Field, + eth_verkle_constants.EC_P_Aff, + eth_verkle_constants.IPAProof, + eth_verkle_constants.MultiProof, + eth_verkle_constants.VerkleDomain, + eth_verkle_constants.PrecomputedWeights, + eth_verkle_constants.IPASettings, + eth_verkle_constants.VerkleSeed, + eth_verkle_constants.Bytes, + eth_verkle_constants.VerkleIPAProofSerialized, + eth_verkle_constants.VerkleMultiproofSerialized, + eth_verkle_constants.IpaTranscript, + eth_verkle_constants.Coord, + eth_verkle_constants.generator # Barycentric Formula for Verkle # ------------------------------------------------------------ export - barycentric_form.newPrecomputedWeights, - barycentric_form.computeBarycentricWeights, - barycentric_form.computeBarycentricCoefficients, - barycentric_form.getInvertedElement, - barycentric_form.getWeightRatios, - barycentric_form.getBarycentricInverseWeight, - barycentric_form.divisionOnDomain + barycentric_form.newPrecomputedWeights, + barycentric_form.computeBarycentricWeights, + barycentric_form.computeBarycentricCoefficients, + barycentric_form.getInvertedElement, + barycentric_form.getWeightRatios, + barycentric_form.getBarycentricInverseWeight, + barycentric_form.divisionOnDomain # Common Math Utils for Verkle # ------------------------------------------------------------ export - common_utils.generate_random_points, - common_utils.computeInnerProducts, - common_utils.computeInnerProducts, - common_utils.foldScalars, - common_utils.foldPoints, - common_utils.computeNumRounds, - common_utils.pedersen_commit_varbasis + common_utils.generate_random_points, + common_utils.computeInnerProducts, + common_utils.computeInnerProducts, + common_utils.foldScalars, + common_utils.foldPoints, + common_utils.computeNumRounds, + common_utils.pedersen_commit_varbasis # IPA Prover for Verkle # ------------------------------------------------------------ export - ipa_prover.genIPAConfig, - ipa_prover.createIPAProof, - ipa_prover.serializeVerkleIPAProof, - ipa_prover.deserializeVerkleIPAProof, - ipa_prover.isIPAProofEqual + ipa_prover.genIPAConfig, + ipa_prover.createIPAProof, + ipa_prover.serializeVerkleIPAProof, + ipa_prover.deserializeVerkleIPAProof, + ipa_prover.isIPAProofEqual # IPA Verifier for Verkle # ------------------------------------------------------------ export - ipa_verifier.generateChallengesForIPA, - ipa_verifier.checkIPAProof + ipa_verifier.generateChallengesForIPA, + ipa_verifier.checkIPAProof # Multiproof for Verkle # ------------------------------------------------------------ export - multiproof.domainToFrElem, - multiproof.domainToFrElem, - multiproof.computePowersOfElem, - multiproof.createMultiProof, - multiproof.verifyMultiProof, - multiproof.serializeVerkleMultiproof, - multiproof.deserializeVerkleMultiproof + multiproof.domainToFrElem, + multiproof.domainToFrElem, + multiproof.computePowersOfElem, + multiproof.createMultiProof, + multiproof.verifyMultiProof, + multiproof.serializeVerkleMultiproof, + multiproof.deserializeVerkleMultiproof + + +# Transcript Utils for Verkle +# ------------------------------------------------------------ +export + transcript_gen.newTranscriptGen, + transcript_gen.messageAppend, + transcript_gen.messageAppend_u64, + transcript_gen.domainSeparator, + transcript_gen.pointAppend, + transcript_gen.scalarAppend, + transcript_gen.generateChallengeScalar diff --git a/constantine/serialization/codecs_banderwagon.nim b/constantine/serialization/codecs_banderwagon.nim index 32c9be39..006a6807 100644 --- a/constantine/serialization/codecs_banderwagon.nim +++ b/constantine/serialization/codecs_banderwagon.nim @@ -65,8 +65,6 @@ func make_scalar_mod_order*(reduced_scalar: var Fr[Banderwagon], src: array[32, res = true return res - - func serialize*(dst: var array[32, byte], P: EC_Prj): CttCodecEccStatus = ## Serialize a Banderwagon point(x, y) in the format ## diff --git a/research/kzg/strided_views.nim b/research/kzg/strided_views.nim index 20794e5b..a738cd4d 100644 --- a/research/kzg/strided_views.nim +++ b/research/kzg/strided_views.nim @@ -37,6 +37,9 @@ func `[]=`*[T](v: var View[T], idx: int, val: T) {.inline.} = # Experimental views indeed ... cast[ptr UncheckedArray[T]](v.data)[v.offset + idx*v.stride] = val +template toOpenArray*[T](v: View[T]): openArray[T] = + v.data.toOpenArray(0, v.len-1) + func toView*[T](oa: openArray[T]): View[T] {.inline.} = result.len = oa.len result.stride = 1 diff --git a/tests/t_ethereum_verkle_ipa_primitives.nim b/tests/t_ethereum_verkle_ipa_primitives.nim index a5a9dbf8..a7282b3a 100644 --- a/tests/t_ethereum_verkle_ipa_primitives.nim +++ b/tests/t_ethereum_verkle_ipa_primitives.nim @@ -107,7 +107,7 @@ suite "Barycentric Form Tests": lagrange_values.testPoly256(testVals) var precomp {.noInit.}: PrecomputedWeights - precomp.newPrecomputedWeights() + precomp.newPrecomputedWeights() var bar_coeffs {.noInit.}: array[256, Fr[Banderwagon]] bar_coeffs.computeBarycentricCoefficients(precomp, p_outside_dom) @@ -137,6 +137,40 @@ suite "Barycentric Form Tests": doAssert expected0.toHex(littleEndian) == expected1.toHex(littleEndian), "Issue Barycentric Precomputes" testBarycentricPrecomputeCoefficients() + + test "Divide on Domain using Barycentric Precomputes": + + proc testDivideOnDomain()= + + var points: array[VerkleDomain, Coord] + for k in 0 ..< VerkleDomain: + var x: Fr[Banderwagon] + x.fromInt(k) + + points[k].x = x + var res: Fr[Banderwagon] + res.evalFunc(x) + points[k].y = res + + var precomp {.noInit.}: PrecomputedWeights + precomp.newPrecomputedWeights() + + var indx = uint8(1) + + var evaluations: array[VerkleDomain, Fr[Banderwagon]] + for i in 0 ..< VerkleDomain: + evaluations[i] = points[i].y + + var quotient: array[VerkleDomain, Fr[Banderwagon]] + quotient.divisionOnDomain(precomp, indx, evaluations) + + doAssert quotient[255].toHex(littleEndian) == "0x616b0e203a877177e2090013a77ce4ea8726941aac613b532002f3653d54250b", "Issue with Divide on Domain using Barycentric Precomputes!" + + testDivideOnDomain() + + + + # ############################################################ # # Test for Random Point Generation and CRS Consistency @@ -148,11 +182,10 @@ suite "Random Elements Generation and CRS Consistency": proc testGenPoints()= var ipaConfig {.noInit.}: IPASettings - var ipaTranscript {.noInit.}: IpaTranscript[sha256, 32] - discard ipaConfig.genIPAConfig(ipaTranscript) + discard ipaConfig.genIPAConfig() var basisPoints {.noInit.}: array[256, EC_P] - basisPoints.generate_random_points(ipaTranscript, 256) + basisPoints.generate_random_points(256) var arr_byte {.noInit.}: array[256, array[32, byte]] discard arr_byte.serializeBatch(basisPoints) @@ -174,11 +207,10 @@ suite "Computing the Correct Vector Commitment": test "Test for Vector Commitments from Verkle Test Vectors by @Ignacio": proc testVectorComm() = var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - let stat1 = ipaConfig.genIPAConfig(ipaTranscript) + discard ipaConfig.genIPAConfig() var basisPoints: array[256, EC_P] - basisPoints.generate_random_points(ipaTranscript, 256) + basisPoints.generate_random_points(256) var test_scalars {.noInit.}: array[256, Fr[Banderwagon]] @@ -189,7 +221,7 @@ suite "Computing the Correct Vector Commitment": commitment.pedersen_commit_varbasis(basisPoints, basisPoints.len, test_scalars, test_scalars.len) var arr22 {.noInit.}: Bytes - let stat33 = arr22.serialize(commitment) + discard arr22.serialize(commitment) doAssert "0x524996a95838712c4580220bb3de453d76cffd7f732f89914d4417bc8e99b513" == arr22.toHex(), "bit string does not match expected" testVectorComm() @@ -376,6 +408,26 @@ suite "Transcript Tests": testVec3() + test "Transcript testing with point append": + proc testVec4()= + + # Initializing a new transcript state + var tr {.noInit.}: sha256 + + # Generating with a new label + tr.newTranscriptGen(asBytes"simple_protocol") + + var gen {.noInit.}: EC_P + gen.fromAffine(Banderwagon.getGenerator()) + + tr.pointAppend(asBytes"generator", gen) + + var challenge {.noInit.}: matchingOrderBigInt(Banderwagon) + challenge.generateChallengeScalar(tr, asBytes"simple_challenge") + + doAssert challenge.toHex(littleEndian) == "0x8c2dafe7c0aabfa9ed542bb2cbf0568399ae794fc44fdfd7dff6cc0e6144921c", "Issue with pointAppend" + testVec4() + # ############################################################ # # Test for IPA Proofs @@ -386,44 +438,151 @@ suite "IPA proof tests": test "Test for initiating IPA proof configuration": proc testMain()= var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - let stat1 = ipaConfig.genIPAConfig(ipaTranscript) + let stat1 = ipaConfig.genIPAConfig() doAssert stat1 == true, "Could not generate new IPA Config properly!" testMain() - test "Test for IPA proof equality": - proc testIPAProofEquality()= - var point: Fr[Banderwagon] + test "Verfify IPA Proof inside the domain by @Ignacio": + proc testIPAProofInDomain()= + + var commitmentBytes {.noInit.} : array[32, byte] + commitmentBytes.fromHex(IPAPedersenCommitment) + + var commitment: EC_P + discard commitment.deserialize(commitmentBytes) + + var evalPoint: Fr[Banderwagon] + evalPoint.fromInt(IPAEvaluationPoint) + + var evaluationResultFr: Fr[Banderwagon] + evaluationResultFr.fromHex(IPAEvaluationResultFr) + + var serializedIPAProof: VerkleIPAProofSerialized + serializedIPAProof.fromHex(IPASerializedProofVec) + + var proof {.noInit.}: IPAProof + discard proof.deserializeVerkleIPAProof(serializedIPAProof) + var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - discard ipaConfig.genIPAConfig(ipaTranscript) + discard ipaConfig.genIPAConfig() + + var tr {.noInit.}: sha256 + tr.newTranscriptGen(asBytes"ipa") + + var ok: bool + var got {.noInit.}: EC_P + ok = ipaConfig.checkIPAProof(tr, got, commitment, proof, evalPoint, evaluationResultFr) + + doAssert ok == true, "ipaConfig.checkIPAProof: Unexpected Failure!" + + testIPAProofInDomain() + test "Test for IPA proof consistency": + proc testIPAProofConsistency()= + + #from a shared view + var point: Fr[Banderwagon] + point.fromInt(2101) + + #from the prover's side + var testVals: array[256, int] = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + ] + var poly: array[256, Fr[Banderwagon]] + poly.testPoly256(testVals) + + var ipaConfig {.noInit.}: IPASettings + discard ipaConfig.genIPAConfig() + + var prover_transcript {.noInit.}: sha256 + prover_transcript.newTranscriptGen(asBytes"test") + + var prover_comm: EC_P + prover_comm.pedersen_commit_varbasis(ipaConfig.SRS, ipaConfig.SRS.len, poly, poly.len) - var testGeneratedPoints: array[256, EC_P] - testGeneratedPoints.generate_random_points(ipaTranscript, 256) + var pcb {.noInit.}: array[32, byte] + discard pcb.serialize(prover_comm) - var prover_transcript: sha256 + doAssert pcb.toHex() == "0x1b9dff8f5ebbac250d291dfe90e36283a227c64b113c37f1bfb9e7a743cdb128", "Issue with computing commitment" + + var ipaProof1 {.noInit.}: IPAProof + let stat11 = ipaProof1.createIPAProof(prover_transcript, ipaConfig, prover_comm, poly, point) + doAssert stat11 == true, "Problem creating IPA proof 1" + + var lagrange_coeffs: array[256, Fr[Banderwagon]] + lagrange_coeffs.computeBarycentricCoefficients(ipaConfig.precompWeights, point) + + var op_point: Fr[Banderwagon] + op_point.computeInnerProducts(lagrange_coeffs, poly) + + + doAssert op_point.toHex(littleEndian) == "0x4a353e70b03c89f161de002e8713beec0d740a5e20722fd5bd68b30540a33208", "Issue with computing commitment" + + testIPAProofConsistency() + + test "Test for IPA proof equality": + proc testIPAProofEquality()= + var prover_transcript {.noInit.}: sha256 prover_transcript.newTranscriptGen(asBytes"ipa") #from a shared view - point.fromInt(12345) + var point: Fr[Banderwagon] + point.fromInt(123456789) #from the prover's side - var testVals: array[5, int] = [1,2,3,4,5] + var testVals: array[14, int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] var poly: array[256, Fr[Banderwagon]] poly.testPoly256(testVals) + var ipaConfig {.noInit.}: IPASettings + discard ipaConfig.genIPAConfig() + + var arr_byte {.noInit.}: array[256, array[32, byte]] + discard arr_byte.serializeBatch(ipaConfig.SRS) + + doAssert arr_byte[0].toHex() == "0x01587ad1336675eb912550ec2a28eb8923b824b490dd2ba82e48f14590a298a0", "Failed to generate the 1st point!" + doAssert arr_byte[255].toHex() == "0x3de2be346b539395b0c0de56a5ccca54a317f1b5c80107b0802af9a62276a4d8", "Failed to generate the 256th point!" + var prover_comm: EC_P - prover_comm.pedersen_commit_varbasis(testGeneratedPoints,testGeneratedPoints.len, poly, poly.len) + prover_comm.pedersen_commit_varbasis(ipaConfig.SRS, ipaConfig.SRS.len, poly, poly.len) - var ipaProof1: IPAProof + var ipaProof1 {.noInit.}: IPAProof let stat11 = ipaProof1.createIPAProof(prover_transcript, ipaConfig, prover_comm, poly, point) doAssert stat11 == true, "Problem creating IPA proof 1" - var ipaProof2: IPAProof - let stat22 = ipaProof2.createIPAProof(prover_transcript, ipaConfig, prover_comm, poly, point) + var prv1_ser {.noInit.}: VerkleIPAProofSerialized + discard prv1_ser.serializeVerkleIPAProof(ipaProof1) + + var point2: Fr[Banderwagon] + point2.fromInt(123456789) + + var ipaConfig2 {.noInit.}: IPASettings + discard ipaConfig2.genIPAConfig() + + var testGeneratedPoints2: array[256, EC_P] + testGeneratedPoints2.generate_random_points(256) + + var prover_transcript2 {.noInit.}: sha256 + prover_transcript2.newTranscriptGen(asBytes"ipa") + + var testVals2: array[14, int] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14] + var poly2: array[256, Fr[Banderwagon]] + poly2.testPoly256(testVals2) + + var prover_comm2 {.noInit.}: EC_P + prover_comm2.pedersen_commit_varbasis(testGeneratedPoints2,testGeneratedPoints2.len, poly2, poly2.len) + + var ipaProof2 {.noInit.}: IPAProof + let stat22 = ipaProof2.createIPAProof(prover_transcript2, ipaConfig, prover_comm, poly, point) doAssert stat22 == true, "Problem creating IPA proof 2" - var stat33: bool + var stat33 = false stat33 = ipaProof1.isIPAProofEqual(ipaProof2) doAssert stat33 == true, "IPA proofs aren't equal" @@ -431,13 +590,12 @@ suite "IPA proof tests": test "Test for IPA Proof of Creation and Verification": proc testIPAProofCreateAndVerify()= - var point : Fr[Banderwagon] - var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - discard ipaConfig.genIPAConfig(ipaTranscript) + var point {.noInit.}: Fr[Banderwagon] + var ipaConfig {.noInit.}: IPASettings + discard ipaConfig.genIPAConfig() var testGeneratedPoints: array[256,EC_P] - testGeneratedPoints.generate_random_points(ipaTranscript,256) + testGeneratedPoints.generate_random_points(256) # from a shared view point.fromInt(123456789) @@ -447,17 +605,17 @@ suite "IPA proof tests": var poly: array[256,Fr[Banderwagon]] poly.testPoly256(testVals) - var prover_comm : EC_P + var prover_comm {.noInit.}: EC_P prover_comm.pedersen_commit_varbasis(testGeneratedPoints, testGeneratedPoints.len, poly, poly.len) - var prover_transcript: sha256 + var prover_transcript {.noInit.}: sha256 prover_transcript.newTranscriptGen(asBytes"ipa") var ipaProof: IPAProof let stat = ipaProof.createIPAProof(prover_transcript, ipaConfig, prover_comm, poly, point) doAssert stat == true, "Problem creating IPA proof" - var precomp : PrecomputedWeights + var precomp {.noInit.}: PrecomputedWeights precomp.newPrecomputedWeights() var lagrange_coeffs : array[VerkleDomain, Fr[Banderwagon]] @@ -475,7 +633,8 @@ suite "IPA proof tests": verifier_transcript.newTranscriptGen(asBytes"ipa") var ok: bool - ok = ipaConfig.checkIPAProof(verifier_transcript, verifier_comm, ipaProof, point, innerProd) + var got {.noInit.}: EC_P + ok = ipaConfig.checkIPAProof(verifier_transcript, got, verifier_comm, ipaProof, point, innerProd) doAssert ok == true, "Issue in checking IPA proof!" testIPAProofCreateAndVerify() @@ -492,55 +651,55 @@ suite "Multiproof Tests": test "IPA Config test for Multiproofs": proc testIPAConfigForMultiproofs()= var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - let stat1 = ipaConfig.genIPAConfig(ipaTranscript) + let stat1 = ipaConfig.genIPAConfig() doAssert stat1 == true, "Could not initialise new IPA config for multiproofs!" testIPAConfigForMultiproofs() test "Multiproof Creation and Verification": proc testMultiproofCreationAndVerification()= - var ipaConfig: IPASettings - var ipaTranscript: IpaTranscript[sha256, 32] - let stat1 = ipaConfig.genIPAConfig(ipaTranscript) - - var testGeneratedPoints: array[256, EC_P] - testGeneratedPoints.generate_random_points(ipaTranscript, 256) + var ipaConfig {.noInit.}: IPASettings + discard ipaConfig.genIPAConfig() var testVals: array[14, int] = [1,1,1,4,5,6,7,8,9,10,11,12,13,14] - var poly : array[256, Fr[Banderwagon]] + var poly: array[256, Fr[Banderwagon]] poly.testPoly256(testVals) - - var precomp : PrecomputedWeights - precomp.newPrecomputedWeights() + + var prover_comm: EC_P + prover_comm.pedersen_commit_varbasis(ipaConfig.SRS, ipaConfig.SRS.len, poly, poly.len) #Prover's view - var prover_transcript: sha256 + var prover_transcript {.noInit.}: sha256 prover_transcript.newTranscriptGen(asBytes"multiproof") - - var prover_comm: EC_P - prover_comm.pedersen_commit_varbasis(testGeneratedPoints,testGeneratedPoints.len, poly, poly.len) - var one : Fr[Banderwagon] + var one: Fr[Banderwagon] one.setOne() - var Cs : array[VerkleDomain, EC_P] - var Fs : array[VerkleDomain, array[VerkleDomain, Fr[Banderwagon]]] - var Zs : array[VerkleDomain, uint8] - var Ys : array[VerkleDomain, Fr[Banderwagon]] + var Cs: seq[EC_P] + var Fs: array[VerkleDomain, array[VerkleDomain, Fr[Banderwagon]]] - Cs[0] = prover_comm + for i in 0 ..< VerkleDomain: + for j in 0 ..< VerkleDomain: + Fs[i][j].setZero() + + var Zs: seq[int] + var Ys: seq[Fr[Banderwagon]] + + Cs.add(prover_comm) + Fs[0] = poly - Zs[0] = 1 - Ys[0] = one - var multiproof: MultiProof + Zs.add(0) + Ys.add(one) + + var multiproof {.noInit.}: MultiProof var stat_create_mult: bool - stat_create_mult = multiproof.createMultiProof(prover_transcript, ipaConfig, Cs, Fs, Zs, precomp, testGeneratedPoints) + stat_create_mult = multiproof.createMultiProof(prover_transcript, ipaConfig, Cs, Fs, Zs) doAssert stat_create_mult.bool() == true, "Multiproof creation error!" + #Verifier's view var verifier_transcript: sha256 verifier_transcript.newTranscriptGen(asBytes"multiproof") @@ -551,6 +710,46 @@ suite "Multiproof Tests": doAssert stat_verify_mult.bool() == true, "Multiproof verification error!" testMultiproofCreationAndVerification() + + test "Verify Multiproof in all Domain and Ranges but one by @Ignacio": + proc testVerifyMultiproofVec()= + + var commitment_bytes {.noInit.}: array[32, byte] + commitment_bytes.fromHex(MultiProofPedersenCommitment) + + var commitment {.noInit.}: EC_P + discard commitment.deserialize(commitment_bytes) + + var evaluationResultFr {.noInit.}: Fr[Banderwagon] + evaluationResultFr.fromHex(MultiProofEvaluationResult) + + var serializeVerkleMultiproof: VerkleMultiproofSerialized + serializeVerkleMultiproof.fromHex(MultiProofSerializedVec) + + var multiproof {.noInit.}: MultiProof + discard multiproof.deserializeVerkleMultiproof(serializeVerkleMultiproof) + + var ipaConfig {.noInit.}: IPASettings + discard ipaConfig.genIPAConfig() + + var Cs: array[VerkleDomain, EC_P] + var Zs: array[VerkleDomain, int] + var Ys: array[VerkleDomain, Fr[Banderwagon]] + + Cs[0] = commitment + Ys[0] = evaluationResultFr + + for i in 0 ..< VerkleDomain: + var tr {.noInit.}: sha256 + tr.newTranscriptGen(asBytes"multiproof") + Zs[0] = i + var ok: bool + ok = multiproof.verifyMultiproof(tr, ipaConfig, Cs, Ys, Zs) + + if i == MultiProofEvaluationPoint: + doAssert ok == true, "Issue with Multiproof!" + + testVerifyMultiproofVec() test "Multiproof Serialization and Deserialization (Covers IPAProof Serialization and Deserialization as well)": proc testMultiproofSerDe() = diff --git a/tests/t_ethereum_verkle_ipa_test_helper.nim b/tests/t_ethereum_verkle_ipa_test_helper.nim index 0162c0b6..80166a17 100644 --- a/tests/t_ethereum_verkle_ipa_test_helper.nim +++ b/tests/t_ethereum_verkle_ipa_test_helper.nim @@ -44,6 +44,22 @@ func ipaEvaluate* [Fr] (res: var Fr, poly: openArray[Fr], point: Fr, n: static tmp.prod(powers[i], poly[i]) res.sum(res,tmp) +func evalFunc* (res: var Fr[Banderwagon], x: Fr[Banderwagon])= + var tmpa {.noInit.}: Fr[Banderwagon] + var one {.noInit.}: Fr[Banderwagon] + one.setOne() + tmpa.diff(x, one) + + var tmpb {.noInit.}: Fr[Banderwagon] + tmpb.sum(x, one) + + var tmpc = one + for i in 0 ..< 253: + tmpc *= x + + res.prod(tmpa, tmpb) + res *= tmpc + func truncate* [Fr] (res: var openArray[Fr], s: openArray[Fr], to: int, n: static int)= for i in 0 ..< to: res[i] = s[i] @@ -150,42 +166,6 @@ func setEval* [Fr] (res: var Fr, x : Fr)= res.prod(tmp_a, tmp_b) res.prod(res,tmp_c) -func evalOutsideDomain* [Fr] (res: var Fr, precomp: PrecomputedWeights, f: openArray[Fr], point: Fr)= - # Evaluating the point z outside of VerkleDomain, here the VerkleDomain is 0-256, whereas the FieldSize is - # everywhere outside of it which is upto a 253 bit number, or 2²⁵³. - var pointMinusDomain: array[VerkleDomain, Fr] - var pointMinusDomain_inv: array[VerkleDomain, Fr] - for i in 0 ..< VerkleDomain: - var i_fr {.noInit.}: Fr - i_fr.fromInt(i) - - pointMinusDomain[i].diff(point, i_fr) - pointMinusDomain_inv[i].inv(pointMinusDomain[i]) - - var summand: Fr - summand.setZero() - - for x_i in 0 ..< pointMinusDomain_inv.len: - var weight: Fr - weight.getBarycentricInverseWeight(precomp, x_i) - var term: Fr - term.prod(weight, f[x_i]) - term *= pointMinusDomain_inv[x_i] - - summand.sum(summand,term) - - res.setOne() - - for i in 0 ..< VerkleDomain: - var i_fr: Fr - i_fr.fromInt(i) - - var tmp: Fr - tmp.diff(point, i_fr) - res *= tmp - - res *= summand - func testPoly256* [Fr] (res: var openArray[Fr], polynomialUint: openArray[int])= doAssert polynomialUint.len <= 256, "Cannot exceed 256 coeffs!" @@ -217,6 +197,28 @@ func getDegreeOfPoly*(res: var int, p: openArray[Fr]) = else: res = -1 +###################################################################### +## +## +## Test Vector for Verifying Multiproof in all Domain Ranges but one +## +## +####################################################################### +const MultiProofPedersenCommitment*: string = "0x5532395cf72b9d6b2252d968cf7fd8923262d3d17fce836a93144a1dc1b59e31" +const MultiProofEvaluationPoint*: int = 8 +const MultiProofEvaluationResult*: string = "0x0000000000000000000000000000000000000000000000000000000000000009" +const MultiProofSerializedVec*: string = "0x61f191c5ad8217b10318ad49f6c43b08a78f4f2788738b5c0fe11eac1878868667750c4fecfbf562628deed76a86982a5bbc3884b92017f71352e976fc5724502513b175a9d55787d58a18e8d21b3f7f7f41f7a0773bf81c957377c5a1de261635d11fe5ff83e8cca5d15aec75683fa1140755066b3972e0d9145e18a4bca26d3490dd54ae955df0caa17e93a788a42cb653ecb5a04c766328c457fe473e5365362dfff36827ced93127cd489364e6884dfc8a8f9ce9e15e27de49ac0827c00e6999c18d4b6966951eec028dc8d74b9a0057e51e97535cd43368f714b2c284c22c3ee5fc99d2ea22115444e0ee543283fbab1e6da03bc3ec7fe1a3dc4cd05d5c515cf783163a9a9ede3878d8f21187cbd2935b75893a2e5611a47ba11b5c69a417c24319b7ccbe43c71c12db43400816b22c749b48d5df0e9fd599801aa515277039062d9987d6ad2e91f96fd261b5f6bf6abf1e1905eb414ad91d17a234809750646e029b2e3ead9c22bd859fb9087ee77d37f3db6663136e81ef971782b99f30a05daa505542ce074b9ba1772b41b3c789a454f726455b95b8fb21af14e4da1262a48536037c0f7b8e9320f83d4cf144b22329e463ceaaf234c51f469965c54463f51dbce440583deca338451b981e9f4534da4e4f417a5844d71be57fa89748440255d9a76a2350cde4f454a8325d348522e81649e9980a204a2435ad0de5566ed7afd2aa250bf5ee0dc56e416a6a84876d979aa52753d9eec97137482113c9e5e42ee6365896f671e6932b1e5bf66b70001f1fef440d730a2844071b8b14" +################################################################### +## +## +## Test Vector for Verifying IPA Proof inside the Domain +## +## +################################################################### +const IPAPedersenCommitment*: string = "0x68a798550a3e2ea3a2a91e1307e4ef06fb35d8df543f903ce9ea4edd75de7706" +const IPAEvaluationPoint*: int = 13 +const IPAEvaluationResultFr*: string = "0x000000000000000000000000000000000000000000000000000000000000000e" +const IPASerializedProofVec*: string = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d3e383cf2ca36482707617daf4230f2261cff2abeb98a7d1e139cf386970f7a67cea4e0dcf8c437e5cd9852d95613a255ef625412a3ac7fb1a0d27227a32a7c1292f14b7c189f033c91217f02b34c7832958afc7ae3bb498b29ca08277dc60d1c53bb5f07280c16238a7f99c059cbbdbbc933bef4b74d604721a09b526aac1751a4bdf0df2d303418e7e5642ac4aacc730625514c87a4bcce5369cc4c1e1d2a1ee9125e09db763e7d99fa857928fabeb94ba822d5cf1cc8f5be372683ee7089082c0ca302a243f0124cc25319d069e0c689f03e4cb32e266fffd4b8c9a5e1cb2c708dc7960531ecea4331e376d7f6604228fc0606a08bda95ee3350c8bca83f37b23160af7bae3db95f0c66ed4535fc5397b43dcdc1d09c1e3a0376a6705d916d96cb64feb47d00ebf1ddbad7eaf3b5d8c381d31098c5c8a909793bd6063c2f0450320af78de387938261eba3e984271f31c3f71a55b33631b90505f8209b384aa55feb1c1c72a5e2abce15f24eb18715a309f5517ac3079c64c8ff157d3e35d5bad17b86f9599b1e34f1f4b7c6600a83913261645a0811fba0ad1ed104fe0c" ################################################################### ## ##