mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
180 lines
3.3 KiB
Python
180 lines
3.3 KiB
Python
import numpy as np
|
|
|
|
# Lets prove we know the answer to x**3 + x + 5 == 35 (x = 5)
|
|
|
|
# We break it down into these statements:
|
|
|
|
# L1: s1 = x * x
|
|
# L2: y = s1 * x
|
|
# L3: s2 = y + x
|
|
# L4: out = s2 + 5
|
|
|
|
# Statements are of the form:
|
|
# a * b = c
|
|
|
|
# s1 = x * x
|
|
# OR a * b = c, where a = x, b = x and c = s1
|
|
L1 = np.array([
|
|
# a b c
|
|
[0, 0, 0], # 1
|
|
[1, 1, 0], # x
|
|
[0, 0, 0], # out
|
|
[0, 0, 1], # s1
|
|
[0, 0, 0], # y
|
|
[0, 0, 0] # s2
|
|
])
|
|
|
|
# y = s1 * x
|
|
L2 = np.array([
|
|
# a b c
|
|
[0, 0, 0], # 1
|
|
[0, 1, 0], # x
|
|
[0, 0, 0], # out
|
|
[1, 0, 0], # s1
|
|
[0, 0, 1], # y
|
|
[0, 0, 0] # s2
|
|
])
|
|
|
|
# s2 = y + x
|
|
L3 = np.array([
|
|
# a b c
|
|
[0, 1, 0], # 1
|
|
[1, 0, 0], # x
|
|
[0, 0, 0], # out
|
|
[0, 0, 0], # s1
|
|
[1, 0, 0], # y
|
|
[0, 0, 1] # s2
|
|
])
|
|
|
|
# out = s2 + 5
|
|
L4 = np.array([
|
|
# a b c
|
|
[5, 1, 0], # 1
|
|
[0, 0, 0], # x
|
|
[0, 0, 1], # out
|
|
[0, 0, 0], # s1
|
|
[0, 0, 0], # y
|
|
[1, 0, 0] # s2
|
|
])
|
|
|
|
a = np.array([L.transpose()[0] for L in (L1, L2, L3, L4)])
|
|
b = np.array([L.transpose()[1] for L in (L1, L2, L3, L4)])
|
|
c = np.array([L.transpose()[2] for L in (L1, L2, L3, L4)])
|
|
print("A")
|
|
print(a)
|
|
print("B")
|
|
print(b)
|
|
print("C")
|
|
print(c)
|
|
|
|
# The witness
|
|
s = np.array([
|
|
1,
|
|
3,
|
|
35,
|
|
9,
|
|
27,
|
|
30
|
|
])
|
|
print()
|
|
|
|
#print(s * a * s * b - s * c)
|
|
for a_i, b_i, c_i in zip(a, b, c):
|
|
assert sum(s * a_i) * sum(s * b_i) - sum(s * c_i) == 0
|
|
|
|
print("R1CS done.")
|
|
print()
|
|
|
|
def factorial(x):
|
|
r = 1
|
|
for x_i in range(2, x + 1):
|
|
r *= x_i
|
|
return r
|
|
|
|
def combinations(n, r):
|
|
return factorial(n) / (factorial(n - r) * factorial(r))
|
|
|
|
def lagrange(points):
|
|
result = np.poly1d([0])
|
|
for i, (x_i, y_i) in enumerate(points):
|
|
poly = np.poly1d([y_i])
|
|
for j, (x_j, y_j) in enumerate(points):
|
|
if i == j:
|
|
continue
|
|
poly *= np.poly1d([1, -x_j]) / (x_i - x_j)
|
|
#print(poly)
|
|
#print(poly(1), poly(2), poly(3))
|
|
result += poly
|
|
return result
|
|
|
|
# 1.5, -5.5, 7
|
|
#poly = lagrange([(1, 3), (2, 2), (3, 4)])
|
|
#print(poly)
|
|
|
|
def make_qap(a):
|
|
a_qap = []
|
|
a_polys = []
|
|
for a_i in a.transpose():
|
|
poly = lagrange(list(enumerate(a_i, start=1)))
|
|
coeffs = poly.c.tolist()
|
|
if len(coeffs) < 4:
|
|
coeffs = [0] * (4 - len(coeffs)) + coeffs
|
|
a_qap.append(coeffs)
|
|
a_polys.append(poly)
|
|
a_qap = np.array(a_qap)
|
|
print(a_qap)
|
|
return a_polys
|
|
|
|
print("A")
|
|
a_polys = make_qap(a)
|
|
print("B")
|
|
b_polys = make_qap(b)
|
|
print("C")
|
|
c_polys = make_qap(c)
|
|
|
|
def check(polys, x):
|
|
results = []
|
|
for poly in polys:
|
|
results.append(int(poly(x)))
|
|
return results
|
|
|
|
print()
|
|
print("A results at x", check(a_polys, 1))
|
|
print()
|
|
print("B results at x", check(b_polys, 1))
|
|
print()
|
|
print("C results at x", check(c_polys, 1))
|
|
|
|
def combine_polys(polys):
|
|
r = np.poly1d([0])
|
|
for s_i, p_i in zip(s, polys):
|
|
r += s_i * p_i
|
|
return r
|
|
|
|
print()
|
|
print()
|
|
A = combine_polys(a_polys)
|
|
print("A =")
|
|
print(A)
|
|
B = combine_polys(b_polys)
|
|
print("B =")
|
|
print(B)
|
|
C = combine_polys(c_polys)
|
|
print("C =")
|
|
print(C)
|
|
print()
|
|
t = A * B - C
|
|
print("t =")
|
|
print(t)
|
|
|
|
# 4 statements in our R1CS: L1, L2, L3, L4
|
|
divisor_poly = np.poly1d([1])
|
|
for x in range(1, 4 + 1):
|
|
divisor_poly *= np.poly1d([1, -x])
|
|
|
|
quot, remainder = np.polydiv(t, divisor_poly)
|
|
assert len(remainder.c) == 1
|
|
print()
|
|
print("Result of QAP:")
|
|
print(int(remainder.c[0]))
|