|
|
@@ -0,0 +1,334 @@
|
|
|
+{
|
|
|
+ "cells": [
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# setup \n"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 41,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# simple 101 group\n",
|
|
|
+ "F101 = IntegerModRing(101)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 42,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# define elliptic curve with coefficient 0(degree 1), 3(degree 0)\n",
|
|
|
+ "E = EllipticCurve(F101, [0,3])"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 43,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# define polynomial ring on F101, then extended in Galois field\n",
|
|
|
+ "R.<X> = PolynomialRing(F101)\n",
|
|
|
+ "K.<X> = GF(101**2, modulus = x^2+2)\n",
|
|
|
+ "E2 = EllipticCurve(K, [0,3])\n",
|
|
|
+ "# EC generator at (1,2)\n",
|
|
|
+ "G=E2([1,2])"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 44,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# the order of G is r=17, the embedding degree it's the smallest k such that r|p^k -1, thus k=2\n",
|
|
|
+ "## if you keep adding G to itself, it would get only 17 unique values r=17\n",
|
|
|
+ "## group base p=101\n",
|
|
|
+ "G2 = E2([36,31*X])\n",
|
|
|
+ "# structured reference string SRS\n",
|
|
|
+ "## in kate commitment, here you create SRS, and release the toxic waste\n",
|
|
|
+ "## for random value rand=2\n",
|
|
|
+ "rand=2\n",
|
|
|
+ "G1_SRS = [(rand**i)*G for i in range(7)]\n",
|
|
|
+ "G2_SRS = [rand**i*G2 for i in range(2)]"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 45,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "N=G.order()\n",
|
|
|
+ "F17=Integers(N)\n",
|
|
|
+ "F17.square_roots_of_one()\n",
|
|
|
+ "# witness values for random [1,4,-1,-4]\n",
|
|
|
+ "w = vector(F17, [1,4,-1,-4])\n",
|
|
|
+ "w\n",
|
|
|
+ "k1=2; k2=3\n",
|
|
|
+ "k1*w\n",
|
|
|
+ "k2*w\n",
|
|
|
+ "A = matrix(F17, [[1**i for i in range (4)], [4**i for i in range (4)], [16**i for i in range(4)], [13**i for i in range(4)]])\n",
|
|
|
+ "Ai = A.inverse()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 46,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "s=2\n",
|
|
|
+ "zeta=5\n",
|
|
|
+ "beta=12\n",
|
|
|
+ "gamma=13\n",
|
|
|
+ "vega=12\n",
|
|
|
+ "alpha = 15\n",
|
|
|
+ "ql_coef = [0,0,1,0] # multiplication a1*b1 : q left mulitplication coefficient for l+ r + m + c = rhs\n",
|
|
|
+ "qr_coef = [0,0,1,0] # multiplication a2*b2'\n",
|
|
|
+ "qm_coef = [1,1,0,0] # addition gate a3+b3\n",
|
|
|
+ "qo_coef = [-1,-1,0,0] # ??\n",
|
|
|
+ "qc_coef = [0,0,-30,0] #??\n",
|
|
|
+ "P.<x> = F17[];x=P.0\n",
|
|
|
+ "ql = P(list(Ai*vector(F17, ql_coef)))\n",
|
|
|
+ "qr = P(list(Ai*vector(F17, qr_coef)))\n",
|
|
|
+ "qm = P(list(Ai*vector(F17, qm_coef)))\n",
|
|
|
+ "qo = P(list(Ai*vector(F17, qo_coef)))\n",
|
|
|
+ "qc = P(list(Ai*vector(F17, qc_coef)))\n",
|
|
|
+ "#public setup polynomials SRS are ql,qr,qm,qo,qc\n",
|
|
|
+ "ql,qr,qm,qo,qc\n",
|
|
|
+ "#\n",
|
|
|
+ "# equality constraints ??\n",
|
|
|
+ "sa = P(list(Ai*vector(F17, [2,3,12,13]))) # ??\n",
|
|
|
+ "sb = P(list(Ai*vector(F17, [1,15,8,9]))) # ??\n",
|
|
|
+ "sc = P(list(Ai*vector(F17, [4,16,14,5]))) # ?? \n",
|
|
|
+ "sa,sb,sc\n",
|
|
|
+ "# blinding values bld1-bld9\n",
|
|
|
+ "bld1=7\n",
|
|
|
+ "bld2=4\n",
|
|
|
+ "bld3=11\n",
|
|
|
+ "bld4=12\n",
|
|
|
+ "bld5=16\n",
|
|
|
+ "bld6=2\n",
|
|
|
+ "bld7=14\n",
|
|
|
+ "bld8=2\n",
|
|
|
+ "bld9=11"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# proving"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 57,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "def proving():\n",
|
|
|
+ " ## for root 3, the following toxic waste coefficient are:\n",
|
|
|
+ " a_coef = [3,9,27,0] # the left operands: a1,a2,a3,a5 \n",
|
|
|
+ " b_coef = [3,3,3,0] # the right operands: b1,b2,b3,b5\n",
|
|
|
+ " c_coef = [9,27,0,0] # the output: c1,c2,c3,c5\n",
|
|
|
+ " fa = P(list(Ai*vector(F17, a_coef)))\n",
|
|
|
+ " fb = P(list(Ai*vector(F17, b_coef)))\n",
|
|
|
+ " fc = P(list(Ai*vector(F17, c_coef)))\n",
|
|
|
+ " # solution polynomials are fa,fb,fc\n",
|
|
|
+ " # round 1\n",
|
|
|
+ " # target polynomial that vanishes at root of unity \n",
|
|
|
+ " Z = x**4-1\n",
|
|
|
+ " # random blinding values b1-b9 = [7,4,11,12,16,2]\n",
|
|
|
+ " a = (bld1*x+bld2)*Z+fa\n",
|
|
|
+ " b = (bld3*x+bld4)*Z+fb\n",
|
|
|
+ " c = (bld5*x+bld6)*Z+fc\n",
|
|
|
+ " ### choose s=2\n",
|
|
|
+ " a_s = ZZ(a(s))*G\n",
|
|
|
+ " b_s = ZZ(b(s))*G\n",
|
|
|
+ " c_s = ZZ(c(s))*G\n",
|
|
|
+ " p = (a_s,b_s,c_s)\n",
|
|
|
+ " # round 2\n",
|
|
|
+ " ### compute permutation challenges (beta,gamma) as hash of the transcript\n",
|
|
|
+ " #for simplicity\n",
|
|
|
+ " acc=1 #accumulator\n",
|
|
|
+ " for i in range(4): #TODO parameterize number of gates\n",
|
|
|
+ " nominator = ((a(w[i])+beta*w[i]+gamma)*(b(w[i])+beta*k1*w[i]+gamma)*(c(w[i])+beta*k2*w[i]+gamma))\n",
|
|
|
+ " denominator = ((a(w[i])+beta*sa(w[i])+gamma)*(b(w[i])+beta*sb(w[i])+gamma)*(c(w[i])+beta*sc(w[i])+gamma))\n",
|
|
|
+ " acc = acc*nominator/denominator\n",
|
|
|
+ " acc=P(list(Ai*vector(F17,[1,12,10,1]))) #TODO parameterize\n",
|
|
|
+ " Zx = (bld7*x**bld8+bld9*x+7)*Z+acc\n",
|
|
|
+ " Z_s = ZZ(Zx(s))*G\n",
|
|
|
+ " # round 3\n",
|
|
|
+ " L=P(list(Ai*vector(F17, [1,0,0,0]))) #TODO parameterize\n",
|
|
|
+ " t1Z = a*b*qm+a*ql+b*qr+c*qo+qc\n",
|
|
|
+ " t2Z = (a+beta*x+gamma)*(b+k1*beta*x+gamma)*(c+k2*beta*x+gamma)*Zx*alpha\n",
|
|
|
+ " Zw = Zx(w[1]*x)\n",
|
|
|
+ " t3Z= -(a+beta*sa+gamma)*(b+beta*sb+gamma)*(c+beta*sc+gamma)*Zw*alpha\n",
|
|
|
+ " t4Z = (Zx-1)*L*alpha**2\n",
|
|
|
+ " tZ = t1Z+t2Z+t3Z+t4Z\n",
|
|
|
+ " ## if everything goes well, then the following should divide without remainders\n",
|
|
|
+ " t=P(tZ/Z)\n",
|
|
|
+ " t_list = t.list()\n",
|
|
|
+ " t_lo=t_list[0:6]\n",
|
|
|
+ " t_mid=t_list[6:12]\n",
|
|
|
+ " t_hi=t_list[12:]\n",
|
|
|
+ " t_lo_s=ZZ(P(t_lo)(s))*G\n",
|
|
|
+ " t_mid_s=ZZ(P(t_mid)(s))*G\n",
|
|
|
+ " t_hi_s=ZZ(P(t_hi)(s))*G\n",
|
|
|
+ " t_lo_s,t_mid_s,t_hi_s\n",
|
|
|
+ " # Round 4\n",
|
|
|
+ " a_=a(zeta)\n",
|
|
|
+ " b_=b(zeta)\n",
|
|
|
+ " c_=c(zeta)\n",
|
|
|
+ " sa_=sa(zeta)\n",
|
|
|
+ " sb_=sb(zeta)\n",
|
|
|
+ " t_=t(zeta)\n",
|
|
|
+ " zw_=Zx(zeta*w[1])\n",
|
|
|
+ " l_=L(zeta)\n",
|
|
|
+ " r1 = a_*b_*qm+a_*ql+b_*qr+c_*qo+qc\n",
|
|
|
+ " r2 = ((a_+beta*zeta+gamma)*(b_+beta*k1*zeta+gamma)*(c_+beta*k2*zeta+gamma)*Zx)*alpha\n",
|
|
|
+ " r3=-(a_+beta*sa_+gamma)*(b_+beta*sb_+gamma)*beta*zw_*sc*alpha\n",
|
|
|
+ " r4=Zx*l_*alpha**2\n",
|
|
|
+ " r=r1+r2+r3+r4\n",
|
|
|
+ " r_=r(zeta)\n",
|
|
|
+ " # Round 5\n",
|
|
|
+ " v1 = P(t_lo)\n",
|
|
|
+ " v2=zeta**6*P(t_mid)\n",
|
|
|
+ " v3=zeta**12*P(t_hi)\n",
|
|
|
+ " v4=-t_\n",
|
|
|
+ " v5 = vega*(r-r_)+vega**2*(a-a_)+vega**3*(b-b_)+vega**4*(c-c_)+vega**5*(sa-sa_)+vega**6*(sb-sb_)\n",
|
|
|
+ " W=v1+v2+v3+v4+v5\n",
|
|
|
+ " ## opening proof polynomial\n",
|
|
|
+ " Wz=W/(x-zeta)\n",
|
|
|
+ " Wzw=(Zx-zw_)/(x-zeta*w[1])\n",
|
|
|
+ " Wz_s=ZZ(Wz(s))*G\n",
|
|
|
+ " Wzw_s=ZZ(Wzw(s))*G\n",
|
|
|
+ " Wz_s,Wzw_s\n",
|
|
|
+ " proof = (a_s,b_s,c_s,Z_s,t_lo_s,t_mid_s,t_hi_s,Wz_s,Wzw_s,a_,b_,c_,sa_,sb_,r_,zw_)\n",
|
|
|
+ " return proof"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 58,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "a_s,b_s,c_s,Z_s,t_lo_s,t_mid_s,t_hi_s,Wz_s,Wzw_s,a_,b_,c_,sa_,sb_,r_,zw_ = proving()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# verification"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 61,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "def verify():\n",
|
|
|
+ " ## TODO (1) verify that all those points are in the curve G1\n",
|
|
|
+ " ## TODO (2) verify that the bar values are part of Fp^7 group\n",
|
|
|
+ " ## TODO (3) validate that w_i (roots of unity) are in F_p^l\n",
|
|
|
+ " ### verifier processed input\n",
|
|
|
+ " qm_s = ZZ(qm(s))*G\n",
|
|
|
+ " ql_s = ZZ(ql(s))*G\n",
|
|
|
+ " qr_s = ZZ(qr(s))*G\n",
|
|
|
+ " qo_s = ZZ(qo(s))*G\n",
|
|
|
+ " qc_s = ZZ(qc(s))*G\n",
|
|
|
+ " sa_s = ZZ(sa(s))*G\n",
|
|
|
+ " sb_s = ZZ(sb(s))*G\n",
|
|
|
+ " sc_s = ZZ(sc(s))*G\n",
|
|
|
+ " ## (4) compute challenges beta, gamma, alpha, zeta, veta, upsilon as in prover description from the common inputs, public input, and elements of zk-snark\n",
|
|
|
+ " epsilon=4 # only this is missing\n",
|
|
|
+ " ## (5) ZERO POLYNOMIAL EVALUATION\n",
|
|
|
+ " Z_z=F17(zeta**4-1)\n",
|
|
|
+ " ## (6) lagrange polynomial evaluation \n",
|
|
|
+ " L1_z=F17((zeta**4-1)/(4*(zeta-1)))\n",
|
|
|
+ " ## TODO(7) public input polynomial evaluation \n",
|
|
|
+ " ## quotient polynomial evaluation\n",
|
|
|
+ " t_=(r_-((a_+beta*sa_+gamma)*(b_+beta*sb_+gamma)*(c_+gamma)*zw_)*alpha-L1_z*alpha**2)/Z_z;t_\n",
|
|
|
+ " ## (9) part of batched opynomimal commitment\n",
|
|
|
+ " d1=ZZ(a_*b_*vega)*qm_s+ZZ(a_*vega)*ql_s+ZZ(b_*vega)*qr_s+ZZ(c_*vega)*qo_s+vega*qc_s\n",
|
|
|
+ " d2=ZZ(((a_+beta*zeta+gamma)*(b_+beta*k1*zeta+gamma)*(c_+beta*k2*zeta+gamma)*alpha*vega)+L1_z*alpha**2*vega+F17(epsilon))*Z_s\n",
|
|
|
+ " d3=-ZZ((a_+beta*sa_+gamma)*(b_+beta*sb_+gamma)*alpha*vega*beta*zw_)*sc_s\n",
|
|
|
+ " d=d1+d2+d3;d\n",
|
|
|
+ " ## (10) full batched polynomial commitment [F]1\n",
|
|
|
+ " f=t_lo_s+zeta**6*t_mid_s+zeta**12*t_hi_s+d+vega**2*a_s+vega**3*b_s+vega**4*c_s+vega**5*sa_s+vega**6*sb_s\n",
|
|
|
+ " ## (11) group-encoded batch evaluation [E]1\n",
|
|
|
+ " e=ZZ((t_+vega*r_+vega**2*a_+vega**3*b_+vega**4*c_+vega**5*sa_+vega**6*sb_+epsilon*zw_))*G\n",
|
|
|
+ " ## (12)\n",
|
|
|
+ " x1=Wz_s+epsilon*Wzw_s\n",
|
|
|
+ " x2=s*G2\n",
|
|
|
+ " y1=zeta*Wz_s+ZZ(epsilon*zeta*w[1])*Wzw_s+f-e\n",
|
|
|
+ " y2=G2\n",
|
|
|
+ " x1_=E2(x1)\n",
|
|
|
+ " x2_=E2(x2)\n",
|
|
|
+ " y1_=E2(y1)\n",
|
|
|
+ " y2_=E2(y2)\n",
|
|
|
+ " return x1_.weil_pairing(x2_,17)==y1_.weil_pairing(y2_,17)\n"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 62,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "assert(verify())"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "### references\n",
|
|
|
+ "[1] https://eprint.iacr.org/2019/953.pdf\n",
|
|
|
+ "\n",
|
|
|
+ "[2] https://research.metastate.dev/plonk-by-hand-part-1/\n",
|
|
|
+ "\n",
|
|
|
+ "[3] https://research.metastate.dev/plonk-by-hand-part-2-the-proof/\n"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": []
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "metadata": {
|
|
|
+ "kernelspec": {
|
|
|
+ "display_name": "SageMath 9.3",
|
|
|
+ "language": "sage",
|
|
|
+ "name": "sagemath"
|
|
|
+ },
|
|
|
+ "language_info": {
|
|
|
+ "codemirror_mode": {
|
|
|
+ "name": "ipython",
|
|
|
+ "version": 3
|
|
|
+ },
|
|
|
+ "file_extension": ".py",
|
|
|
+ "mimetype": "text/x-python",
|
|
|
+ "name": "python",
|
|
|
+ "nbconvert_exporter": "python",
|
|
|
+ "pygments_lexer": "ipython3",
|
|
|
+ "version": "3.7.10"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "nbformat": 4,
|
|
|
+ "nbformat_minor": 4
|
|
|
+}
|