| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- # 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
- )
|