mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
104 lines
2.6 KiB
Python
104 lines
2.6 KiB
Python
from bls_py import bls12381
|
|
from bls_py import pairing
|
|
from bls_py import ec
|
|
from bls_py.fields import Fq, Fq2, Fq6, Fq12, bls12381_q as Q
|
|
import random
|
|
import numpy as np
|
|
|
|
# Section 3.3.4 from "Why and How zk-SNARK Works"
|
|
|
|
def rand_scalar():
|
|
return random.randrange(1, bls12381.q)
|
|
|
|
#x = rand_scalar()
|
|
#y = ec.y_for_x(x)
|
|
|
|
g1 = ec.generator_Fq(bls12381)
|
|
g2 = ec.generator_Fq2(bls12381)
|
|
|
|
null = ec.AffinePoint(Fq(Q, 0), Fq(Q, 1), True, bls12381)
|
|
assert g1 + null == g1
|
|
|
|
#################################
|
|
# Verifier (trusted setup)
|
|
#################################
|
|
|
|
# samples a random value (a secret)
|
|
s = rand_scalar()
|
|
|
|
# calculates encryptions of s for all powers i in 0 to d
|
|
# E(s^i) = g^s^i
|
|
d = 10
|
|
encrypted_powers = [
|
|
g1 * (s**i) for i in range(d)
|
|
]
|
|
|
|
# evaluates unencrypted target polynomial with s: t(s)
|
|
target = (s - 1) * (s - 2)
|
|
|
|
# encrypted values of s provided to the prover
|
|
# Actual values of s are toxic waste and discarded
|
|
|
|
#################################
|
|
# Prover
|
|
#################################
|
|
|
|
# E(p(s)) = p(s)G
|
|
# = c_d s^d G + ... + c_1 s^1 G + c_0 s^0 G
|
|
# = s^3 G - 3 s^2 G + 2 s G
|
|
# E(h(s)) = sG
|
|
# t(s) = s^2 - 3s + 2
|
|
# E(h(s)) t(s) = s^3 G - 3 s^2 G + 2 s G
|
|
|
|
# Lets test these manually:
|
|
|
|
e_s = encrypted_powers
|
|
e_p_s = e_s[3] - 3 * e_s[2] + 2 * e_s[1]
|
|
e_h_s = e_s[1]
|
|
t_s = s**2 - 3*s + 2
|
|
assert t_s == target
|
|
assert e_p_s == e_h_s * t_s
|
|
|
|
#############################
|
|
|
|
# x^3 - 3x^2 + 2x
|
|
main_poly = np.poly1d([1, -3, 2, 0])
|
|
# (x - 1)(x - 2)
|
|
target_poly = np.poly1d([1, -1]) * np.poly1d([1, -2])
|
|
|
|
# Calculates polynomial h(x) = p(x) / t(x)
|
|
cofactor, remainder = main_poly / target_poly
|
|
assert remainder == np.poly1d([0])
|
|
|
|
# Using encrypted powers and coefficients, evaluates
|
|
# E(p(s)) and E(h(s))
|
|
def evaluate(poly, encrypted_powers):
|
|
coeffs = list(poly.coef)[::-1]
|
|
result = null
|
|
for power, coeff in zip(encrypted_powers, coeffs):
|
|
#print(coeff, power)
|
|
coeff = int(coeff)
|
|
# I have to do this for some strange reason
|
|
# Because if coeff is negative and I do += power * coeff
|
|
# then it gives me a different result than what I expect
|
|
if coeff < 0:
|
|
result -= power * (-coeff)
|
|
else:
|
|
result += power * coeff
|
|
return result
|
|
|
|
encrypted_poly = evaluate(main_poly, encrypted_powers)
|
|
assert encrypted_poly == e_p_s
|
|
encrypted_cofactor = evaluate(cofactor, encrypted_powers)
|
|
|
|
# resulting g^p and g^h are provided to the verifier
|
|
|
|
#################################
|
|
# Verifier
|
|
#################################
|
|
|
|
# Last check that p = t(s) h
|
|
|
|
assert encrypted_poly == encrypted_cofactor * target
|
|
|