mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
140 lines
3.2 KiB
Python
140 lines
3.2 KiB
Python
# Algorithm:
|
|
# if w { a * b } else { a + b }
|
|
|
|
# Equation:
|
|
# f(w, a, b) = w(ab) + (1 - w)(a + b) = v
|
|
|
|
# w(ab) + a + b - w(ab) = v
|
|
# w(ab - a - b) = v - a - b
|
|
|
|
# Constraints:
|
|
# 1: [1 a] [1 b] [1 m]
|
|
# 2: [1 w] [1 m, -1 a, -1 b] = [1 v, -1 a, -1 b]
|
|
# 3: [1 w] [1 w] [1 w]
|
|
|
|
# f(1, 4, 2) = 8
|
|
|
|
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
|
|
from finite_fields.modp import IntegersModP
|
|
from finite_fields.polynomial import polynomialsOver
|
|
import random
|
|
|
|
n = bls12381.n
|
|
|
|
g1 = ec.generator_Fq(bls12381)
|
|
g2 = ec.generator_Fq2(bls12381)
|
|
|
|
mod_field = IntegersModP(n)
|
|
poly = polynomialsOver(mod_field).factory
|
|
|
|
def lagrange(points):
|
|
result = poly([0])
|
|
for i, (x_i, y_i) in enumerate(points):
|
|
p = poly([y_i])
|
|
for j, (x_j, y_j) in enumerate(points):
|
|
if i == j:
|
|
continue
|
|
p *= poly([-x_j, 1]) / (x_i - x_j)
|
|
#print(poly)
|
|
#print(poly(1), poly(2), poly(3))
|
|
result += p
|
|
return result
|
|
|
|
left_variables = {
|
|
"a": lagrange([
|
|
(1, 1), (2, 0), (3, 0)
|
|
]),
|
|
"w": lagrange([
|
|
(1, 0), (2, 1), (3, 1)
|
|
])
|
|
}
|
|
|
|
right_variables = {
|
|
"m": lagrange([
|
|
(1, 0), (2, 1), (3, 0)
|
|
]),
|
|
"a": lagrange([
|
|
(1, 0), (2, -1), (3, 0)
|
|
]),
|
|
"b": lagrange([
|
|
(1, 1), (2, -1), (3, 0)
|
|
]),
|
|
"w": lagrange([
|
|
(1, 0), (2, 0), (3, 1)
|
|
]),
|
|
}
|
|
|
|
out_variables = {
|
|
"m": lagrange([
|
|
(1, 1), (2, 0), (3, 0)
|
|
]),
|
|
"v": lagrange([
|
|
(1, 0), (2, 1), (3, 0)
|
|
]),
|
|
"a": lagrange([
|
|
(1, 0), (2, -1), (3, 0)
|
|
]),
|
|
"b": lagrange([
|
|
(1, 0), (2, -1), (3, 0)
|
|
]),
|
|
"w": lagrange([
|
|
(1, 0), (2, 0), (3, 1)
|
|
]),
|
|
}
|
|
|
|
private_inputs = {
|
|
"w": 1,
|
|
"a": 3,
|
|
"b": 2
|
|
}
|
|
|
|
private_inputs["m"] = private_inputs["a"] * private_inputs["b"]
|
|
private_inputs["v"] = \
|
|
private_inputs["w"] * (
|
|
private_inputs["m"] - private_inputs["a"] - private_inputs["b"]) \
|
|
+ private_inputs["a"] + private_inputs["b"]
|
|
assert private_inputs["v"] == 6
|
|
|
|
left_variable_poly = (
|
|
private_inputs["a"] * left_variables["a"]
|
|
+ private_inputs["w"] * left_variables["w"]
|
|
)
|
|
right_variable_poly = (
|
|
private_inputs["m"] * right_variables["m"]
|
|
+ private_inputs["a"] * right_variables["a"]
|
|
+ private_inputs["b"] * right_variables["b"]
|
|
+ private_inputs["w"] * right_variables["w"]
|
|
)
|
|
out_variable_poly = (
|
|
private_inputs["m"] * out_variables["m"]
|
|
+ private_inputs["v"] * out_variables["v"]
|
|
+ private_inputs["a"] * out_variables["a"]
|
|
+ private_inputs["b"] * out_variables["b"]
|
|
+ private_inputs["w"] * out_variables["w"]
|
|
)
|
|
|
|
# (x - 1)(x - 2)(x - 3)
|
|
target_poly = poly([-1, 1]) * poly([-2, 1]) * poly([-3, 1])
|
|
|
|
def poly_call(poly, x):
|
|
result = mod_field(0)
|
|
for degree, coeff in enumerate(poly):
|
|
result += coeff * (x**degree)
|
|
return result.n
|
|
|
|
assert poly_call(target_poly, 1) == 0
|
|
assert poly_call(target_poly, 2) == 0
|
|
assert poly_call(target_poly, 3) == 0
|
|
|
|
main_poly = left_variable_poly * right_variable_poly - out_variable_poly
|
|
cofactor_poly = main_poly / target_poly
|
|
|
|
assert (
|
|
left_variable_poly * right_variable_poly == \
|
|
cofactor_poly * target_poly + out_variable_poly
|
|
)
|
|
|