From c741f558f8275f278b34a7c47751cf26acab3da9 Mon Sep 17 00:00:00 2001 From: feltroid Prime <96737978+feltroidprime@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:38:12 +0700 Subject: [PATCH] Tower pairings & Timelock encryption (#239) --- .github/workflows/cairo.yml | 2 +- .github/workflows/e2e.yml | 2 +- .github/workflows/hydra.yml | 2 +- README.md | 2 +- docs/gitbook/installation/developer-setup.md | 2 +- hydra/garaga/definitions.py | 24 +- hydra/garaga/drand/client.py | 10 +- hydra/garaga/drand/tlock.py | 226 + .../garaga/extension_field_modulo_circuit.py | 6 +- hydra/garaga/hints/tower_backup.py | 13 + hydra/garaga/modulo_circuit.py | 46 +- hydra/garaga/modulo_circuit_structs.py | 68 + .../precompiled_circuits/all_circuits.py | 205 +- .../compilable_circuits/base.py | 3 +- .../cairo1_tower_pairing.py | 948 +++ .../common_cairo_fustat_circuits.py | 82 +- hydra/garaga/precompiled_circuits/ec.py | 69 +- .../precompiled_circuits/miller_tower.py | 620 ++ .../precompiled_circuits/multi_miller_loop.py | 1 + .../groth16_contract_generator/generator.py | 9 +- .../generator_risc0.py | 3 +- .../drand_calldata.py | 21 +- .../test_writer.py | 139 +- src/.tool-versions | 2 +- src/Scarb.toml | 4 +- src/contracts/drand_quicknet/Scarb.toml | 2 +- .../drand_quicknet/src/drand_verifier.cairo | 1 - .../groth16_example_bls12_381/.tools-versions | 2 +- .../groth16_example_bls12_381/Scarb.toml | 2 +- .../src/groth16_verifier.cairo | 5 +- .../groth16_example_bn254/.tools-versions | 2 +- .../groth16_example_bn254/Scarb.toml | 2 +- .../src/groth16_verifier.cairo | 5 +- src/contracts/risc0_verifier_bn254/Scarb.toml | 2 +- .../src/groth16_verifier.cairo | 5 +- src/contracts/universal_ecip/Scarb.toml | 2 +- src/src/circuits.cairo | 1 + src/src/circuits/dummy.cairo | 1 + src/src/circuits/ec.cairo | 156 +- src/src/circuits/extf_mul.cairo | 1 + src/src/circuits/isogeny.cairo | 1 + src/src/circuits/multi_pairing_check.cairo | 91 +- src/src/circuits/tower_circuits.cairo | 6189 +++++++++++++++++ src/src/core/circuit.cairo | 18 +- src/src/definitions.cairo | 59 +- src/src/ec_ops.cairo | 13 - src/src/ec_ops_g2.cairo | 318 + src/src/groth16.cairo | 4 +- src/src/lib.cairo | 2 + src/src/single_pairing_tower.cairo | 636 ++ src/src/tests.cairo | 1 + src/src/tests/tower_pairing_tests.cairo | 1297 ++++ src/src/utils/drand.cairo | 429 +- tests/contracts_e2e/fixtures/devnet.py | 2 + tests/contracts_e2e/install_devnet.sh | 2 +- tests/hydra/circuits/test_ec.py | 89 + tests/hydra/test_drand.py | 77 +- tools/make/bytecode_check.sh | 6 + tools/make/setup.sh | 6 +- 59 files changed, 11761 insertions(+), 177 deletions(-) create mode 100644 hydra/garaga/drand/tlock.py create mode 100644 hydra/garaga/precompiled_circuits/compilable_circuits/cairo1_tower_pairing.py create mode 100644 hydra/garaga/precompiled_circuits/miller_tower.py create mode 100644 src/src/circuits/tower_circuits.cairo create mode 100644 src/src/ec_ops_g2.cairo create mode 100644 src/src/single_pairing_tower.cairo create mode 100644 src/src/tests/tower_pairing_tests.cairo create mode 100644 tests/hydra/circuits/test_ec.py diff --git a/.github/workflows/cairo.yml b/.github/workflows/cairo.yml index 11c461c8..a7316429 100644 --- a/.github/workflows/cairo.yml +++ b/.github/workflows/cairo.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.8.2" + scarb-version: "2.8.4" - run: scarb fmt --check working-directory: src/ - run: cd src/ && scarb test diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index db99719b..451512c9 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -38,7 +38,7 @@ jobs: - name: Setup Scarb uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.8.2" + scarb-version: "2.8.4" - name: Install dependencies run: make setup diff --git a/.github/workflows/hydra.yml b/.github/workflows/hydra.yml index 5e1c0149..4cfbcadc 100644 --- a/.github/workflows/hydra.yml +++ b/.github/workflows/hydra.yml @@ -54,7 +54,7 @@ jobs: - name: Set up Scarb uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.8.2" + scarb-version: "2.8.4" - name: Run make rewrite and check for unstaged changes run: | source venv/bin/activate diff --git a/README.md b/README.md index 2bee203b..4b1920b7 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ To get started with Garaga, you'll need to have some tools and dependencies inst Ensure you have the following installed: - [Python 3.10](https://www.python.org/downloads/) - /!\ Make sure `python3.10` is a valid command in your terminal. The core language used for development. Make sure you have the correct dependencies installed (in particular, GMP) for the `fastecdsa` python package. See [here](https://pypi.org/project/fastecdsa/#installing) for linux and [here](https://github.com/AntonKueltz/fastecdsa/issues/74) for macos. -- [Scarb 2.8.2](https://docs.swmansion.com/scarb/download.html) - The Cairo package manager. Comes with Cairo inside. Requires [Rust](https://www.rust-lang.org/tools/install). +- [Scarb 2.8.4](https://docs.swmansion.com/scarb/download.html) - The Cairo package manager. Comes with Cairo inside. Requires [Rust](https://www.rust-lang.org/tools/install). ##### Optionally : diff --git a/docs/gitbook/installation/developer-setup.md b/docs/gitbook/installation/developer-setup.md index 4904407f..fbd20414 100644 --- a/docs/gitbook/installation/developer-setup.md +++ b/docs/gitbook/installation/developer-setup.md @@ -7,7 +7,7 @@ icon: wrench To work with Garaga, you need the following dependencies : * Python 3.10. The command `python3.10` should be available and working in your terminal. -* [Scarb](https://docs.swmansion.com/scarb/download.html) v2.8.2. +* [Scarb](https://docs.swmansion.com/scarb/download.html) v2.8.4. * [Rust](https://www.rust-lang.org/tools/install) Simply clone the [repository](https://github.com/keep-starknet-strange/garaga) : diff --git a/hydra/garaga/definitions.py b/hydra/garaga/definitions.py index a567c444..fb39aaca 100644 --- a/hydra/garaga/definitions.py +++ b/hydra/garaga/definitions.py @@ -831,6 +831,17 @@ def __neg__(self) -> "G1Point": self.iso_point, ) + def to_pyfelt_list(self) -> list[PyFelt]: + field = get_base_field(self.curve_id.value) + return [field(self.x), field(self.y)] + + def serialize_to_cairo(self, name: str, raw: bool = False) -> str: + import garaga.modulo_circuit_structs as structs + + return structs.G1PointCircuit(name=name, elmts=self.to_pyfelt_list()).serialize( + raw + ) + @dataclass(frozen=True) class G2Point: @@ -847,7 +858,7 @@ def __post_init__(self): if self.is_infinity(): return if not self.is_on_curve(): - raise ValueError("G2 Point is not on the curve") + raise ValueError(f"G2 Point is not on the curve {self.curve_id}") @staticmethod def infinity(curve_id: CurveID) -> "G2Point": @@ -956,6 +967,17 @@ def msm(points: list["G2Point"], scalars: list[int]) -> "G2Point": scalar_mul = functools.reduce(lambda acc, p: acc.add(p), muls) return scalar_mul + def to_pyfelt_list(self) -> list[PyFelt]: + field = get_base_field(self.curve_id.value) + return [field(x) for x in self.x + self.y] + + def serialize_to_cairo(self, name: str, raw: bool = False) -> str: + import garaga.modulo_circuit_structs as structs + + return structs.G2PointCircuit(name=name, elmts=self.to_pyfelt_list()).serialize( + raw + ) + @dataclass(slots=True) class G1G2Pair: diff --git a/hydra/garaga/drand/client.py b/hydra/garaga/drand/client.py index 8582b433..a46a885a 100644 --- a/hydra/garaga/drand/client.py +++ b/hydra/garaga/drand/client.py @@ -111,10 +111,10 @@ def deserialize_bls_point(s_string: bytes) -> Union[G1Point, G2Point]: if len(s_string) == 48: # G1 point (compressed) field = get_base_field(CurveID.BLS12_381) y2 = field(x**3 + 4) - y = y2.sqrt() - Y_bit = y.value & 1 - if S_bit != Y_bit: - y = -y + if S_bit == 1: + y = y2.sqrt(min_root=False) + else: + y = y2.sqrt(min_root=True) return G1Point(x, y.value, CurveID.BLS12_381) elif len(s_string) == 96: # G2 point (compressed) field = get_base_field(CurveID.BLS12_381, Fp2) @@ -282,4 +282,4 @@ def print_all_chain_info() -> dict[DrandNetwork, NetworkInfo]: def generate_precomputed_lines_code(precomputed_lines: StructArray) -> str: return f"pub const precomputed_lines: [G2Line; {len(precomputed_lines)//4}] = {precomputed_lines.serialize(raw=True, const=True)};" - print(generate_precomputed_lines_code(precomputed_lines)) + # print(generate_precomputed_lines_code(precomputed_lines)) diff --git a/hydra/garaga/drand/tlock.py b/hydra/garaga/drand/tlock.py new file mode 100644 index 00000000..18b3f635 --- /dev/null +++ b/hydra/garaga/drand/tlock.py @@ -0,0 +1,226 @@ +import hashlib +import secrets +from dataclasses import dataclass + +from garaga.definitions import CURVES, CurveID, G1G2Pair, G1Point, G2Point +from garaga.drand.client import DrandNetwork, digest_func +from garaga.hints.tower_backup import E12 +from garaga.signature import hash_to_curve + + +@dataclass +class CipherText: + U: G2Point + V: bytes + W: bytes + + def __post_init__(self): + assert len(self.V) == len(self.W) == 16 + + def serialize_to_cairo(self): + code = f"""CipherText {{ + U: {self.U.serialize_to_cairo(name="U", raw=True)}, + V: [{', '.join(f'0x{b:02x}' for b in self.V)}], + W: [{', '.join(f'0x{b:02x}' for b in self.W)}], + }} + """ + return code + + +def encrypt_for_round( + drand_public_key: G2Point, round: int, message: bytes, debug: bool = False +) -> CipherText: + assert len(message) == 16, f"Message should be 16 bytes: {len(message)}" + + msg_at_round = digest_func(round) + # print(f"msg_at_round list of ints: {list(msg_at_round)}") + pt_at_round = hash_to_curve(msg_at_round, CurveID.BLS12_381) + + gid: E12 = G1G2Pair.pair([G1G2Pair(p=pt_at_round, q=drand_public_key)]) + + if debug: + # Use a fixed sigma for debugging: + sigma = b"0000000000000000" + else: + sigma: bytes = secrets.token_bytes(16) + + assert len(sigma) == 16 + + hasher = hashlib.sha256() + hasher.update(b"IBE-H3") + hasher.update(sigma) + hasher.update(message) + r = int.from_bytes(expand_message_drand(hasher.digest(), 32), "little") + # print(f"r list of ints: {r}") + r = r % CURVES[CurveID.BLS12_381.value].n + + # U = r * G2 + U = G2Point.get_nG(CurveID.BLS12_381, r) + + # print(f"U: {U}") + # V = sigma XOR H (rGid) + rGid: E12 = gid**r + + # print(f"rGid: {rGid.value_coeffs}") + + rgid_serialized = rGid.serialize() + # Print bytes as hex strings: + # print(f"rGid hex : {rgid_serialized.hex()}") + # print(f"rGid serialized: {list(rgid_serialized)} len: {len(rgid_serialized)}") + rgid_hash = hashlib.sha256() + rgid_hash.update(b"IBE-H2") + rgid_hash.update(rgid_serialized) + rgid_hash = rgid_hash.digest() + # Take first 16 bytes only : + rgid_hash = rgid_hash[:16] + # print(f"rgid_hash hex: {rgid_hash.hex()}") + + V = bytes([a ^ b for a, b in zip(sigma, rgid_hash)]) + # print(f"V hex: {V.hex()}") + + # 6. Compute W = M XOR H(sigma) + W = bytes([a ^ b for a, b in zip(message, rgid_hash)]) + sigma_hash = hashlib.sha256() + sigma_hash.update(b"IBE-H4") + sigma_hash.update(sigma) + sigma_hash = sigma_hash.digest()[:16] # First 16 bytes only + # print(f"sigma_hash hex: {sigma_hash.hex()}") + W = bytes([a ^ b for a, b in zip(message, sigma_hash)]) + # print(f"W hex: {W.hex()}") + + return CipherText(U, V, W) + + +def decrypt_at_round(signature_at_round: G1Point, c: CipherText): + # 1. Compute sigma = V XOR H2(e(rP,Sig)) + + r_gid: E12 = G1G2Pair.pair([G1G2Pair(p=signature_at_round, q=c.U)]) + # for i, v in enumerate(r_gid.value_coeffs): + # print(f"rgid_{i}: {io.int_to_u384(v, as_hex=False)}") + r_gid_serialized = r_gid.serialize() + rgid_hash = hashlib.sha256() + + pre_image = bytearray(b"IBE-H2") + pre_image.extend(r_gid_serialized) + rgid_hash.update(pre_image) + + # for i in range(0, len(pre_image), 4): + # print(f"pre_image[{i}:{i+4}]: {pre_image[i:i+4].hex()}") + + rgid_hash = rgid_hash.digest() + + rgid_hash = rgid_hash[:16] # First 16 bytes only + + sigma = bytes([a ^ b for a, b in zip(c.V, rgid_hash)]) + + # print(f"sigma hex: {sigma.hex()}") + + # 2. Compute Msg = W XOR H4(sigma) + sigma_hash = hashlib.sha256() + sigma_hash.update(b"IBE-H4") + sigma_hash.update(sigma) + sigma_hash = sigma_hash.digest()[:16] # First 16 bytes only + + message = bytes([a ^ b for a, b in zip(c.W, sigma_hash)]) + # print(f"message utf-8: {message.decode('utf-8')}") + + # 3. Check U = G^r + + rh = hashlib.sha256() + rh.update(b"IBE-H3") + rh.update(sigma) + rh.update(message) + rh = rh.digest() + rh = expand_message_drand(rh, 32) + + r = int.from_bytes(rh, "little") + r = r % CURVES[CurveID.BLS12_381.value].n + U = G2Point.get_nG(CurveID.BLS12_381, r) + assert U == c.U + return message + + +def expand_message_drand(msg: bytes, buf_size: int) -> bytes: + BITS_TO_MASK_FOR_BLS12381 = 1 + order = CURVES[CurveID.BLS12_381.value].n + for i in range(1, 65536): # u16::MAX is 65535 + # Hash iteratively: H(i || msg) + h = hashlib.sha256() + pre_image = bytearray(i.to_bytes(2, byteorder="little")) + pre_image.extend(msg) + h.update(pre_image) + hash_result = bytearray(h.digest()) + # Mask the first byte + hash_result[0] >>= BITS_TO_MASK_FOR_BLS12381 + + reversed_hash = hash_result[::-1] + + scalar = int.from_bytes(reversed_hash, "little") % order + if scalar != 0: + return reversed_hash[:buf_size] + + raise ValueError( + "You are insanely unlucky and should have been hit by a meteor before now" + ) + + +def write_cairo1_test(msg: bytes, round: int, network: DrandNetwork): + chain_infos = print_all_chain_info() + chain = chain_infos[network] + master = chain.public_key + ciphertext: CipherText = encrypt_for_round(master, round, msg, debug=True) + + signature_at_round = get_randomness(chain.hash, round).signature_point + _ = decrypt_at_round(signature_at_round, ciphertext) + + comment_with_params_used = f""" + // msg: {msg} + // round: {round} + // network: {network} + """ + code = f""" + #[test] + fn test_decrypt_at_round() {{ + {comment_with_params_used} + {signature_at_round.serialize_to_cairo(name="signature_at_round")} + let ciph = {ciphertext.serialize_to_cairo()}; + let msg_decrypted = decrypt_at_round(signature_at_round, ciph); + assert(msg_decrypted.span() == [{', '.join(f'0x{b:02x}' for b in msg)}].span(), 'wrong msg'); + }} + """ + return code + + +if __name__ == "__main__": + from garaga.drand.client import DrandNetwork, get_randomness, print_all_chain_info + + # chain_infos = print_all_chain_info() + network = DrandNetwork.quicknet + # chain = chain_infos[network] + + # master = chain.public_key + + round = 128 + + msg = b"hello\x00\x00\x00\x00\x00\x00\x00\x00abc" + # ciph = encrypt_for_round(master, round, msg) + + # # print(f"CipherText: {ciph}") + + # # print(f"V : {list(ciph.V)}") + # # print(f"W : {list(ciph.W)}") + + # chain = chain_infos[network] + # beacon = get_randomness(chain.hash, round) + # signature_at_round = beacon.signature_point + + # print(f"signature_at_round: {signature_at_round}") + # msg_decrypted = decrypt_at_round(signature_at_round, ciph) + # assert msg_decrypted == msg + + # print(f"msg utf-8: {msg.decode('utf-8')}") + # print(f"msg_decrypted utf-8: {msg_decrypted.decode('utf-8')}") + + code = write_cairo1_test(msg, round, network) + + print(code) diff --git a/hydra/garaga/extension_field_modulo_circuit.py b/hydra/garaga/extension_field_modulo_circuit.py index 8cecf86a..825ed249 100644 --- a/hydra/garaga/extension_field_modulo_circuit.py +++ b/hydra/garaga/extension_field_modulo_circuit.py @@ -76,9 +76,13 @@ def __init__( init_hash: int = None, hash_input: bool = True, compilation_mode: int = 0, + generic_circuit: bool = False, ) -> None: super().__init__( - name=name, curve_id=curve_id, compilation_mode=compilation_mode + name=name, + curve_id=curve_id, + compilation_mode=compilation_mode, + generic_circuit=generic_circuit, ) self.class_name = "ExtensionFieldModuloCircuit" self.extension_degree = extension_degree diff --git a/hydra/garaga/hints/tower_backup.py b/hydra/garaga/hints/tower_backup.py index 4893e397..6199f1ab 100644 --- a/hydra/garaga/hints/tower_backup.py +++ b/hydra/garaga/hints/tower_backup.py @@ -414,6 +414,9 @@ def __mul__(self, other): z0 = c + b return E12([z0, z1], self.curve_id) + def conjugate(self): + return E12([self.c0, -self.c1], self.curve_id) + def square(self): c0 = self.c0 - self.c1 c3 = -(self.c1.mul_by_non_residue()) + self.c0 @@ -472,6 +475,16 @@ def __pow__(self, p: int): return result + def serialize(self) -> bytes: + # Implement serialization like ark-ff: + serialized = bytearray() + bit_size = CURVES[self.curve_id].p.bit_length() + byte_size = (bit_size + 7) // 8 + for c in self.value_coeffs[::-1]: + serialized.extend(c.to_bytes(byte_size, byteorder="big")) + + return bytes(serialized) + def get_tower_object(x: list[PyFelt], curve_id: int, extension_degree: int): if extension_degree == 2: diff --git a/hydra/garaga/modulo_circuit.py b/hydra/garaga/modulo_circuit.py index baecbb87..74dc5d73 100644 --- a/hydra/garaga/modulo_circuit.py +++ b/hydra/garaga/modulo_circuit.py @@ -341,6 +341,7 @@ def __init__( self.compilation_mode = compilation_mode self.exact_output_refs_needed = None self.input_structs: list[Cairo1SerializableStruct] = [] + self.do_not_inline = False @property def values_offset(self) -> int: @@ -629,6 +630,32 @@ def fp2_mul(self, X: list[ModuloCircuitElement], Y: list[ModuloCircuitElement]): ), ] + def fp2_mul_by_non_residue(self, X: list[ModuloCircuitElement]): + assert len(X) == 2 and all(isinstance(x, ModuloCircuitElement) for x in X) + if self.curve_id == 1: + # Non residue (1,1) + # (a0 + i*a1) * (1 + i) + a_tmp = self.add(X[0], X[1]) + a = self.add(a_tmp, a_tmp) + b = X[0] + z_a0 = self.sub(b, X[1]) + z_a1 = self.sub(self.sub(a, b), X[1]) + return [z_a0, z_a1] + elif self.curve_id == 0: + # Non residue (9, 1) + # (a0 + i*a1) * (9 + i) + a_tmp = self.add(X[0], X[1]) + a = self.mul(a_tmp, self.set_or_get_constant(10)) + b = self.mul(X[0], self.set_or_get_constant(9)) + z_a0 = self.sub(b, X[1]) + z_a1 = self.sub(self.sub(a, b), X[1]) + return [z_a0, z_a1] + + else: + raise ValueError( + f"Unsupported curve id for fp2 mul by non residue: {self.curve_id}" + ) + def fp2_square(self, X: list[ModuloCircuitElement]): # Assumes the irreducible poly is X^2 + 1. # x² = (x0 + i x1)² = (x0² - x1²) + 2 * i * x0 * x1 = (x0+x1)(x0-x1) + i * 2 * x0 * x1. @@ -639,6 +666,16 @@ def fp2_square(self, X: list[ModuloCircuitElement]): self.double(self.mul(X[0], X[1])), ] + def fp2_inv(self, X: list[ModuloCircuitElement]): + assert len(X) == 2 and all(isinstance(x, ModuloCircuitElement) for x in X) + t0 = self.mul(X[0], X[0], comment="Fp2 Inv start") + t1 = self.mul(X[1], X[1]) + t0 = self.add(t0, t1) + t1 = self.inv(t0) + inv0 = self.mul(X[0], t1, comment="Fp2 Inv real part end") + inv1 = self.neg(self.mul(X[1], t1), comment="Fp2 Inv imag part end") + return [inv0, inv1] + def fp2_div(self, X: list[ModuloCircuitElement], Y: list[ModuloCircuitElement]): assert len(X) == len(Y) == 2 and all( isinstance(x, ModuloCircuitElement) and isinstance(y, ModuloCircuitElement) @@ -659,13 +696,8 @@ def fp2_div(self, X: list[ModuloCircuitElement], Y: list[ModuloCircuitElement]): return x_over_y elif self.compilation_mode == 1: # Todo : consider passing as calldata if possible. - t0 = self.mul(Y[0], Y[0], comment="Fp2 Div x/y start : Fp2 Inv y start") - t1 = self.mul(Y[1], Y[1]) - t0 = self.add(t0, t1) - t1 = self.inv(t0) - inv0 = self.mul(Y[0], t1, comment="Fp2 Inv y real part end") - inv1 = self.neg(self.mul(Y[1], t1), comment="Fp2 Inv y imag part end") - return self.fp2_mul(X, [inv0, inv1]) + inv = self.fp2_inv(Y) + return self.fp2_mul(X, inv) def sub_and_assert( self, diff --git a/hydra/garaga/modulo_circuit_structs.py b/hydra/garaga/modulo_circuit_structs.py index 6c9097c2..155dea2e 100644 --- a/hydra/garaga/modulo_circuit_structs.py +++ b/hydra/garaga/modulo_circuit_structs.py @@ -954,6 +954,74 @@ def __len__(self) -> int: return 12 +class E12T(Cairo1SerializableStruct): + def __init__(self, name: str, elmts: list[ModuloCircuitElement]): + super().__init__(name, elmts) + self.members_names = ( + "c0b0a0", + "c0b0a1", + "c0b1a0", + "c0b1a1", + "c0b2a0", + "c0b2a1", + "c1b0a0", + "c1b0a1", + "c1b1a0", + "c1b1a1", + "c1b2a0", + "c1b2a1", + ) + + def extract_from_circuit_output( + self, offset_to_reference_map: dict[int, str] + ) -> str: + assert len(self.elmts) == 12 + code = ( + f"let {self.name}:{self.__class__.__name__} = {self.__class__.__name__}{{\n" + ) + for i, elmt in enumerate(self.elmts): + code += f"{self.members_names[i]}:outputs.get_output({offset_to_reference_map[elmt.offset]}),\n" + code += "};" + return code + + def serialize(self, raw: bool = False, is_option: bool = False) -> str: + if self.elmts is None: + raw_struct = "Option::None" + if raw: + return raw_struct + else: + return f"let {self.name}:Option<{self.__class__.__name__}> = {raw_struct};\n" + else: + assert len(self.elmts) == 12 + + raw_struct = ( + f"{self.__class__.__name__}{{" + + f"{','.join([f'{self.members_names[i]}: {int_to_u384(self.elmts[i].value)}' for i in range(len(self))])}}}" + ) + if is_option: + raw_struct = f"Option::Some({raw_struct})" + if raw: + return raw_struct + else: + return f"let {self.name} = {raw_struct};\n" + + def _serialize_to_calldata(self) -> list[int]: + return io.bigint_split_array(self.elmts, n_limbs=4, prepend_length=False) + + def dump_to_circuit_input(self) -> str: + code = "" + for i in range(len(self)): + code += f"circuit_inputs = circuit_inputs.next_2({self.name}.{self.members_names[i]});\n" + return code + + def __len__(self) -> int: + if self.elmts is not None: + assert len(self.elmts) == 12 + return 12 + else: + return 12 + + class E12DMulQuotient(Cairo1SerializableStruct): def extract_from_circuit_output( self, offset_to_reference_map: dict[int, str] diff --git a/hydra/garaga/precompiled_circuits/all_circuits.py b/hydra/garaga/precompiled_circuits/all_circuits.py index 27832e64..fdfb0d0b 100644 --- a/hydra/garaga/precompiled_circuits/all_circuits.py +++ b/hydra/garaga/precompiled_circuits/all_circuits.py @@ -20,11 +20,30 @@ MPCheckPrepareLambdaRootEvaluations, MPCheckPreparePairs, ) +from garaga.precompiled_circuits.compilable_circuits.cairo1_tower_pairing import ( + E12TCyclotomicSquareCircuit, + E12TCyclotomicSquareCompressedCircuit, + E12TDecompressKarabinaPtIICircuit, + E12TDecompressKarabinaPtINZCircuit, + E12TDecompressKarabinaPtIZCircuit, + E12TFrobeniusCircuit, + E12TFrobeniusCubeCircuit, + E12TFrobeniusSquareCircuit, + E12TInverseCircuit, + E12TMulCircuit, + FP6NegCircuit, + TowerMillerBit0, + TowerMillerBit1, + TowerMillerFinalizeBN, + TowerMillerInitBit, +) from garaga.precompiled_circuits.compilable_circuits.common_cairo_fustat_circuits import ( AccumulateEvalPointChallengeSignedCircuit, AccumulateFunctionChallengeDuplCircuit, AddECPointCircuit, + AddECPointsG2Circuit, DoubleECPointCircuit, + DoubleECPointG2AEq0Circuit, DummyCircuit, EvalFunctionChallengeDuplCircuit, FinalizeFunctionChallengeDuplCircuit, @@ -81,6 +100,31 @@ class CircuitID(Enum): FP12_MUL_ASSERT_ONE = int.from_bytes(b"fp12_mul_assert_one", "big") EVAL_E12D = int.from_bytes(b"eval_e12d", "big") APPLY_ISOGENY = int.from_bytes(b"apply_isogeny", "big") + TOWER_MILLER_BIT0 = int.from_bytes(b"tower_miller_bit0", "big") + TOWER_MILLER_BIT1 = int.from_bytes(b"tower_miller_bit1", "big") + TOWER_MILLER_INIT_BIT = int.from_bytes(b"tower_miller_init_bit", "big") + TOWER_MILLER_FINALIZE_BN = int.from_bytes(b"tower_miller_finalize_bn", "big") + E12T_MUL = int.from_bytes(b"e12t_mul", "big") + E12T_CYCLOTOMIC_SQUARE = int.from_bytes(b"e12t_cyclotomic_square", "big") + E12T_FROBENIUS_SQUARE = int.from_bytes(b"e12t_frobenius_square", "big") + FP6_NEG = int.from_bytes(b"fp6_neg", "big") + E12T_INVERSE = int.from_bytes(b"e12t_inverse", "big") + E12T_FROBENIUS = int.from_bytes(b"e12t_frobenius", "big") + E12T_FROBENIUS_CUBE = int.from_bytes(b"e12t_frobenius_cube", "big") + E12T_CYCLOTOMIC_SQUARE_COMPRESSED = int.from_bytes( + b"e12t_cyclotomic_square_compressed", "big" + ) + E12T_DECOMPRESS_KARABINA_PT_INZ = int.from_bytes( + b"e12t_decompress_karabina_pt_inz", "big" + ) + E12T_DECOMPRESS_KARABINA_PT_IZ = int.from_bytes( + b"e12t_decompress_karabina_pt_iz", "big" + ) + E12T_DECOMPRESS_KARABINA_PT_II = int.from_bytes( + b"e12t_decompress_karabina_pt_ii", "big" + ) + ADD_EC_POINT_G2 = int.from_bytes(b"add_ec_point_g2", "big") + DOUBLE_EC_POINT_G2 = int.from_bytes(b"double_ec_point_g2", "big") ALL_CAIRO_CIRCUITS = { @@ -145,6 +189,16 @@ class CircuitID(Enum): "params": None, "filename": "ec", }, + CircuitID.ADD_EC_POINT_G2: { + "class": AddECPointsG2Circuit, + "params": None, + "filename": "ec", + }, + CircuitID.DOUBLE_EC_POINT_G2: { + "class": DoubleECPointG2AEq0Circuit, + "params": None, + "filename": "ec", + }, CircuitID.MP_CHECK_BIT0_LOOP: { "class": FixedG2MPCheckBit0, "params": [ @@ -226,6 +280,96 @@ class CircuitID(Enum): "filename": "isogeny", "curve_ids": [CurveID.BLS12_381], }, + CircuitID.TOWER_MILLER_BIT0: { + "class": TowerMillerBit0, + "params": [{"n_pairs": k} for k in [1]], + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.TOWER_MILLER_BIT1: { + "class": TowerMillerBit1, + "params": [{"n_pairs": k} for k in [1]], + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.TOWER_MILLER_INIT_BIT: { + "class": TowerMillerInitBit, + "params": [{"n_pairs": k} for k in [1]], + "filename": "tower_circuits", + "curve_ids": [CurveID.BLS12_381], + }, + CircuitID.TOWER_MILLER_FINALIZE_BN: { + "class": TowerMillerFinalizeBN, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254], + }, + CircuitID.E12T_MUL: { + "class": E12TMulCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_CYCLOTOMIC_SQUARE: { + "class": E12TCyclotomicSquareCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_FROBENIUS_SQUARE: { + "class": E12TFrobeniusSquareCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.FP6_NEG: { + "class": FP6NegCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_INVERSE: { + "class": E12TInverseCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_FROBENIUS: { + "class": E12TFrobeniusCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_FROBENIUS_CUBE: { + "class": E12TFrobeniusCubeCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BN254, CurveID.BLS12_381], + }, + CircuitID.E12T_CYCLOTOMIC_SQUARE_COMPRESSED: { + "class": E12TCyclotomicSquareCompressedCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BLS12_381], + }, + CircuitID.E12T_DECOMPRESS_KARABINA_PT_INZ: { + "class": E12TDecompressKarabinaPtINZCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BLS12_381], + }, + CircuitID.E12T_DECOMPRESS_KARABINA_PT_IZ: { + "class": E12TDecompressKarabinaPtIZCircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BLS12_381], + }, + CircuitID.E12T_DECOMPRESS_KARABINA_PT_II: { + "class": E12TDecompressKarabinaPtIICircuit, + "params": None, + "filename": "tower_circuits", + "curve_ids": [CurveID.BLS12_381], + }, } @@ -264,14 +408,56 @@ def initialize_compilation( ) -def write_headers(files: dict[str, open], compilation_mode: int) -> None: +def write_headers( + files: dict[str, open], + compilation_mode: int, + output_sizes_exceeding_limit: dict[str, set[int]], +) -> None: """ - Write the header to the files. + Write the header to the files. Add a specific header if max output length exceeds the limit. """ HEADER = compilation_mode_to_file_header(compilation_mode) - for file in files.values(): + + TEMPLATE = """ +impl CircuitDefinition{num_outputs}< + {elements} +> of core::circuit::CircuitDefinition< + ( + {ce_elements} + ) +> {{ + type CircuitType = + core::circuit::Circuit< + ({elements_tuple},) + >; +}} +impl MyDrp_{num_outputs}< + {elements} +> of Drop< + ( + {ce_elements} + ) +>; +""" + + for filename, file in files.items(): + # Write the header first file.write(HEADER) + # Then write the template for each unique output size exceeding the limit + for num_outputs in sorted(output_sizes_exceeding_limit[filename]): + elements = ", ".join(f"E{i}" for i in range(num_outputs)) + ce_elements = ", ".join(f"CE" for i in range(num_outputs)) + elements_tuple = ", ".join(f"E{i}" for i in range(num_outputs)) + file.write( + TEMPLATE.format( + num_outputs=num_outputs, + elements=elements, + ce_elements=ce_elements, + elements_tuple=elements_tuple, + ) + ) + def compile_circuits( CIRCUITS_TO_COMPILE: dict, @@ -279,6 +465,8 @@ def compile_circuits( codes: dict[str, set[str]], cairo1_full_function_names: dict[str, set[str]], cairo1_tests_functions: dict[str, set[str]], + output_sizes_exceeding_limit: dict[str, set[int]], + limit: int, ) -> None: """ Compile the circuits and write them to the files. @@ -296,6 +484,11 @@ def compile_circuits( filename_key, ) codes[filename_key].update(compiled_circuits) + for circuit_instance in circuit_instances: + output_length = len(circuit_instance.circuit.output) + if output_length > limit: + output_sizes_exceeding_limit[filename_key].add(output_length) + if compilation_mode == 1: cairo1_full_function_names[filename_key].update(full_function_names) generate_cairo1_tests( @@ -380,14 +573,18 @@ def main( filenames_used, codes, cairo1_tests_functions, cairo1_full_function_names, files = ( initialize_compilation(PRECOMPILED_CIRCUITS_DIR, CIRCUITS_TO_COMPILE) ) - write_headers(files, compilation_mode) + output_sizes_exceeding_limit = {filename: set() for filename in filenames_used} + limit = 15 compile_circuits( CIRCUITS_TO_COMPILE, compilation_mode, codes, cairo1_full_function_names, cairo1_tests_functions, + output_sizes_exceeding_limit, + limit, ) + write_headers(files, compilation_mode, output_sizes_exceeding_limit) write_compiled_circuits( files, codes, diff --git a/hydra/garaga/precompiled_circuits/compilable_circuits/base.py b/hydra/garaga/precompiled_circuits/compilable_circuits/base.py index 95c2d2e3..28dbc7a5 100644 --- a/hydra/garaga/precompiled_circuits/compilable_circuits/base.py +++ b/hydra/garaga/precompiled_circuits/compilable_circuits/base.py @@ -125,7 +125,8 @@ def compilation_mode_to_file_header(mode: int) -> str: use core::circuit::CircuitInput as CI; use garaga::definitions::{get_a, get_b, get_p, get_g, get_min_one, G1Point, G2Point, E12D, u288, E12DMulQuotient, G1G2Pair, BNProcessedPair, BLSProcessedPair, MillerLoopResultScalingFactor, G2Line, get_BLS12_381_modulus,get_BN254_modulus}; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; -use core::option::Option;\n +use core::option::Option; +use garaga::single_pairing_tower::E12T;\n """ diff --git a/hydra/garaga/precompiled_circuits/compilable_circuits/cairo1_tower_pairing.py b/hydra/garaga/precompiled_circuits/compilable_circuits/cairo1_tower_pairing.py new file mode 100644 index 00000000..e59e959d --- /dev/null +++ b/hydra/garaga/precompiled_circuits/compilable_circuits/cairo1_tower_pairing.py @@ -0,0 +1,948 @@ +from abc import ABC, abstractmethod +from typing import Dict, List, Optional, Tuple, Type, Union + +import garaga.modulo_circuit_structs as structs +from garaga.definitions import BLS12_381_ID +from garaga.extension_field_modulo_circuit import ModuloCircuit, PyFelt +from garaga.modulo_circuit_structs import ( + Cairo1SerializableStruct, + G2Line, + G2PointCircuit, + u384, + u384Array, +) +from garaga.precompiled_circuits.compilable_circuits.base import ( + BaseEXTFCircuit, + BaseModuloCircuit, +) +from garaga.precompiled_circuits.miller_tower import MillerTowerCircuit + + +def split_4_sized_object_into_tuple_of_2_size( + input: Union[List[PyFelt], Tuple[PyFelt, PyFelt, PyFelt, PyFelt]] +) -> Optional[Tuple[List[PyFelt], List[PyFelt]]]: + if input is None: + return None + assert len(input) == 4, f"Expected input of length 4, got {len(input)}" + return (list(input[0:2]), list(input[2:4])) + + +def parse_precomputed_g1_consts_and_g2_points( + circuit: MillerTowerCircuit, + vars: dict, + n_pairs: int, + bit_1: bool = False, +) -> list[tuple[list[PyFelt], list[PyFelt]]]: + current_points = [] + q_or_q_neg_points = [] if bit_1 else None + for i in range(n_pairs): + circuit.yInv.append(vars[f"yInv_{i}"]) + circuit.xNegOverY.append(vars[f"xNegOverY_{i}"]) + current_points.append( + split_4_sized_object_into_tuple_of_2_size(vars.get(f"Q_{i}", None)) + ) # Return empty list if not present + if bit_1: + q_or_q_neg_points.append( + split_4_sized_object_into_tuple_of_2_size( + vars.get(f"Q_or_Q_neg_{i}", None) + ) # Return empty list if not present + ) + + return current_points, q_or_q_neg_points + + +class BaseTowerMillerLoop(BaseEXTFCircuit, ABC): + def __init__( + self, + name, + curve_id, + auto_run=True, + compilation_mode=1, + n_pairs: int = 1, + ): + assert compilation_mode == 1, "Compilation mode 1 is required for this circuit" + self.n_pairs = n_pairs + super().__init__( + name=name, + curve_id=curve_id, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + self.generic_over_curve = True + + def _initialize_circuit(self): + return MillerTowerCircuit( + self.name, + self.curve_id, + n_pairs=self.n_pairs, + compilation_mode=self.compilation_mode, + ) + + @property + @abstractmethod + def input_map( + self, + ) -> Dict[ + str, + Union[ + Type[Cairo1SerializableStruct], Tuple[Type[Cairo1SerializableStruct], int] + ], + ]: + """ + Define the input map for the circuit in a dict. + The key will be the name of the input variable, also used in the signature of the compiled Cairo code. + The value will be either a Cairo1SerializableStruct type (which defines the struct in the Cairo code), + or a tuple of the type and its size (for Array-like types). + The reason behind this is that each Cairo1SerializableStruct defines the __len__ method, but for the + array-like structs we need to specify the size in advance. + """ + + def _base_input_map(self, bit_type: str) -> dict: + """ + Base input map for the bit 0 and 1 + """ + input_map = {} + + for k in range(self.n_pairs): + input_map[f"yInv_{k}"] = u384 + input_map[f"xNegOverY_{k}"] = u384 + input_map[f"Q_{k}"] = G2PointCircuit + if bit_type == "1": + input_map[f"Q_or_Q_neg_{k}"] = G2PointCircuit + + # Add common inputs + input_map["M_i"] = structs.E12T + + return input_map + + def _process_input(self, circuit: MillerTowerCircuit, input: list[PyFelt]) -> dict: + """ + Method responsible for deserializing the input list of elements into the variables in the input map, + and writing them to the circuit. + The input list is expected to be in the same order as the input map. + Since we use Python 3.10, the input map dict is ordered. + Returns a vars dict with the same keys as the input map, but with the values being the instances of the structs, + each struct holding ModuloCircuitElement(s). + """ + vars = {} + for name, struct_info in self.input_map.items(): + if isinstance(struct_info, tuple) and struct_info[0] == u384Array: + # Handle u384Array with specified size + struct_type, size = struct_info + vars[name] = circuit.write_struct( + struct_type(name, elmts=[input.pop(0) for _ in range(size)]) + ) + elif struct_info == G2Line: + # Internally appended to the precomputed_lines flattened list + circuit.precomputed_lines.extend( + circuit.write_struct( + G2Line(name, elmts=[input.pop(0) for _ in range(4)]) + ) + ) + else: + struct_type = struct_info + # For other types, create a temporary instance to get its length + temp_instance = struct_type( + name, None + ) # Temporary instance with a dummy element + size = len(temp_instance) + if size == 1: + vars[name] = circuit.write_struct( + struct_type(name, elmts=[input.pop(0)]) + ) + else: + # Convert to tuple so that it is Hashable + vars[name] = tuple( + circuit.write_struct( + struct_type(name, elmts=[input.pop(0) for _ in range(size)]) + ) + ) + assert len(input) == 0, f"Expected input of length 0, got {len(input)}" + # Create the precomputed lines generator + circuit._precomputed_lines_generator = ( + circuit._create_precomputed_lines_generator() + ) + return vars + + def build_input(self) -> list[PyFelt]: + """ + Extends the base method of BaseModuloCircuit, by reading the input map and returning a list of random elements of the total expected size. + """ + total_elements = 0 + for name, struct_info in self.input_map.items(): + if isinstance(struct_info, tuple): + # Array-like case + _, size = struct_info + total_elements += size + else: + # For other structs, create a temporary instance to get its length + temp_instance = struct_info(name, None) + total_elements += len(temp_instance) + + return [self.field.random() for _ in range(total_elements)] + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = self._initialize_circuit() + + vars = self._process_input(circuit, input) + return self._execute_circuit_logic(circuit, vars) + + @abstractmethod + def _execute_circuit_logic(self, circuit, vars) -> ModuloCircuit: + """ + Implement the circuit logic using the processed input variables. + """ + + def _execute_circuit_bit_logic_base( + self, circuit: MillerTowerCircuit, vars, bit_type + ): + n_pairs = self.n_pairs + assert n_pairs >= 1, f"n_pairs must be >= 1, got {n_pairs}" + + current_points, q_or_q_neg_points = parse_precomputed_g1_consts_and_g2_points( + circuit, vars, n_pairs, bit_1=(bit_type == "1") + ) + + Mi_sq = circuit.fp12_square(vars["M_i"]) + + new_points, Mi_plus_one = self._process_points( + circuit, current_points, q_or_q_neg_points, Mi_sq, bit_type + ) + + self._extend_output(circuit, new_points, Mi_plus_one) + + return circuit + + def _process_points( + self, + circuit: MillerTowerCircuit, + current_points, + q_or_q_neg_points, + sum_i_prod_k_P, + bit_type, + ): + new_points = [] + if bit_type == "0": + for k in range(self.n_pairs): + T, (lineR0, lineR1) = circuit._double(current_points[k], k) + line = circuit.eval_tower_line( + lineR0 + lineR1, circuit.yInv[k], circuit.xNegOverY[k] + ) + sum_i_prod_k_P = self._multiply_line_evaluations( + circuit, sum_i_prod_k_P, [line], k + ) + new_points.append(T) + elif bit_type == "1": + for k in range(self.n_pairs): + # T, l1, l2 = circuit.double_and_add_step( + # current_points[k], q_or_q_neg_points[k], k + # ) + T, (line1R0, line1R1), (line2R0, line2R1) = circuit._double_and_add( + current_points[k], q_or_q_neg_points[k], k + ) + line1 = circuit.eval_tower_line( + line1R0 + line1R1, circuit.yInv[k], circuit.xNegOverY[k] + ) + line2 = circuit.eval_tower_line( + line2R0 + line2R1, circuit.yInv[k], circuit.xNegOverY[k] + ) + sum_i_prod_k_P = self._multiply_line_evaluations( + circuit, sum_i_prod_k_P, [line1, line2], k + ) + new_points.append(T) + + return new_points, sum_i_prod_k_P + + def _multiply_line_evaluations( + self, + circuit: MillerTowerCircuit, + sum_i_prod_k_P, + lines, + k, + ): + for i, l in enumerate(lines): + sum_i_prod_k_P = circuit.mul_by_line_tower(sum_i_prod_k_P, l) + return sum_i_prod_k_P + + def _extend_output(self, circuit, new_points, Mi_plus_one): + + for i, point in enumerate(new_points): + circuit.extend_struct_output( + G2PointCircuit( + name=f"Q{i}", + elmts=[ + point[0][0], + point[0][1], + point[1][0], + point[1][1], + ], + ) + ) + circuit.extend_struct_output( + structs.E12T(name="Mi_plus_one", elmts=Mi_plus_one) + ) + + +class TowerMillerBit0(BaseTowerMillerLoop): + def __init__( + self, + curve_id: int, + n_pairs: int, + auto_run: bool = True, + compilation_mode: int = 1, + ): + super().__init__( + name=f"tower_miller_bit0_{n_pairs}P", + curve_id=curve_id, + n_pairs=n_pairs, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + @property + def input_map(self): + return self._base_input_map("0") + + def _execute_circuit_logic(self, circuit, vars) -> ModuloCircuit: + return self._execute_circuit_bit_logic_base(circuit, vars, "0") + + +class TowerMillerBit1(BaseTowerMillerLoop): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + n_pairs: int = 1, + compilation_mode: int = 1, + ): + assert compilation_mode == 1, "Compilation mode 1 is required for this circuit" + super().__init__( + name=f"tower_miller_bit1_{n_pairs}P", + curve_id=curve_id, + n_pairs=n_pairs, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + @property + def input_map(self): + return self._base_input_map("1") + + def _execute_circuit_logic(self, circuit, vars) -> ModuloCircuit: + return self._execute_circuit_bit_logic_base(circuit, vars, "1") + + +class TowerMillerInitBit(BaseTowerMillerLoop): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + compilation_mode: int = 1, + n_pairs: int = 3, + ): + super().__init__( + name=f"tower_miller_init_bit_{n_pairs}P", + curve_id=curve_id, + n_pairs=n_pairs, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + @property + def input_map(self): + if self.curve_id == BLS12_381_ID: + input_map = {} + for k in range(self.n_pairs): + input_map[f"yInv_{k}"] = u384 + input_map[f"xNegOverY_{k}"] = u384 + input_map[f"Q_{k}"] = G2PointCircuit + return input_map + else: + raise NotImplementedError(f"Curve {self.curve_id} not implemented") + + def _execute_circuit_logic( + self, circuit: MillerTowerCircuit, vars + ) -> ModuloCircuit: + n_pairs = self.n_pairs + assert n_pairs == 1, f"Only implemented for 1 pair for now, got {n_pairs}" + + current_points, q_or_q_neg_points = parse_precomputed_g1_consts_and_g2_points( + circuit, vars, n_pairs, bit_1=False + ) + + new_points = [] + for k in range(self.n_pairs): + T, (line1R0, line1R1), (line2R0, line2R1) = circuit._triple( + current_points[k], k + ) + + line1 = circuit.eval_tower_line( + line1R0 + line1R1, circuit.yInv[k], circuit.xNegOverY[k] + ) + line2 = circuit.eval_tower_line( + line2R0 + line2R1, circuit.yInv[k], circuit.xNegOverY[k] + ) + # result.C0.B0 = prodLines[0] + # result.C0.B1 = prodLines[1] + # result.C0.B2 = prodLines[2] + # result.C1.B1 = prodLines[3] + # result.C1.B2 = prodLines[4] + ll = circuit.mul_line_by_line_tower(line1, line2) + + new_points.append(T) + + for i, point in enumerate(new_points): + circuit.extend_struct_output( + G2PointCircuit( + name=f"Q{i}", + elmts=[ + point[0][0], + point[0][1], + point[1][0], + point[1][1], + ], + ) + ) + + circuit.extend_struct_output(structs.u384(name="c0b0a0", elmts=[ll[0]])) + circuit.extend_struct_output(structs.u384(name="c0b0a1", elmts=[ll[1]])) + circuit.extend_struct_output(structs.u384(name="c0b1a0", elmts=[ll[2]])) + circuit.extend_struct_output(structs.u384(name="c0b1a1", elmts=[ll[3]])) + circuit.extend_struct_output(structs.u384(name="c0b2a0", elmts=[ll[4]])) + circuit.extend_struct_output(structs.u384(name="c0b2a1", elmts=[ll[5]])) + circuit.extend_struct_output(structs.u384(name="c1b1a0", elmts=[ll[6]])) + circuit.extend_struct_output(structs.u384(name="c1b1a1", elmts=[ll[7]])) + circuit.extend_struct_output(structs.u384(name="c1b2a0", elmts=[ll[8]])) + circuit.extend_struct_output(structs.u384(name="c1b2a1", elmts=[ll[9]])) + + return circuit + + +class TowerMillerFinalizeBN(BaseTowerMillerLoop): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + n_pairs: int = 1, + compilation_mode: int = 1, + ): + + super().__init__( + name=f"tower_miller_finalize_bn_{n_pairs}P", + curve_id=curve_id, + n_pairs=n_pairs, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + @property + def input_map(self): + if self.curve_id == BLS12_381_ID: + return {} + input_map = {} + + for i in range(self.n_pairs): + input_map[f"original_Q{i}"] = G2PointCircuit + input_map[f"yInv_{i}"] = u384 + input_map[f"xNegOverY_{i}"] = u384 + input_map[f"Q_{i}"] = G2PointCircuit + + input_map["Mi"] = structs.E12T + + return input_map + + def _execute_circuit_logic(self, circuit: MillerTowerCircuit, vars): + if self.curve_id == BLS12_381_ID: + return circuit + + n_pairs = self.n_pairs + current_points = [] + for k in range(n_pairs): + circuit.Q.append( + split_4_sized_object_into_tuple_of_2_size( + vars.get(f"original_Q{k}", None) + ) + ) + circuit.yInv.append(vars[f"yInv_{k}"]) + circuit.xNegOverY.append(vars[f"xNegOverY_{k}"]) + current_points.append( + split_4_sized_object_into_tuple_of_2_size(vars.get(f"Q_{k}", None)) + ) + + Mi = vars["Mi"] + + lines = circuit._bn254_finalize_step(current_points) + + for l in lines: + ((l1r0, l1r1), (l2r0, l2r1)) = l + + l1_eval = circuit.eval_tower_line( + l1r0 + l1r1, circuit.yInv[k], circuit.xNegOverY[k] + ) + l2_eval = circuit.eval_tower_line( + l2r0 + l2r1, circuit.yInv[k], circuit.xNegOverY[k] + ) + + ll = circuit.mul_line_by_line_tower(l1_eval, l2_eval) + + ll_full = ll + [ + circuit.set_or_get_constant(0), + circuit.set_or_get_constant(0), + ] + + Mi = circuit.fp12_mul(Mi, ll_full) + + circuit.extend_struct_output(structs.E12T("Mi", elmts=Mi)) + return circuit + + +class E12TMulCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__("e12t_mul", curve_id, auto_run, init_hash, compilation_mode) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # X + input.extend([self.field.random() for _ in range(12)]) # Y + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> MillerTowerCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + X = circuit.write_struct( + structs.E12T("X", elmts=[input.pop(0) for _ in range(12)]) + ) + Y = circuit.write_struct( + structs.E12T("Y", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_mul(X, Y) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class FP6NegCircuit(BaseModuloCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + compilation_mode: int = 1, + ): + super().__init__("fp6_neg", curve_id, auto_run, compilation_mode) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(6)]) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = ModuloCircuit( + self.name, + self.curve_id, + generic_circuit=True, + compilation_mode=self.compilation_mode, + ) + + fp6 = [ + circuit.write_struct(structs.u384(name="b0a0", elmts=[input.pop(0)])), + circuit.write_struct(structs.u384(name="b0a1", elmts=[input.pop(0)])), + circuit.write_struct(structs.u384(name="b1a0", elmts=[input.pop(0)])), + circuit.write_struct(structs.u384(name="b1a1", elmts=[input.pop(0)])), + circuit.write_struct(structs.u384(name="b2a0", elmts=[input.pop(0)])), + circuit.write_struct(structs.u384(name="b2a1", elmts=[input.pop(0)])), + ] + + res = [circuit.neg(fp6[i]) for i in range(6)] + + circuit.extend_struct_output(structs.u384(name="r0", elmts=[res[0]])) + circuit.extend_struct_output(structs.u384(name="r1", elmts=[res[1]])) + circuit.extend_struct_output(structs.u384(name="r2", elmts=[res[2]])) + circuit.extend_struct_output(structs.u384(name="r3", elmts=[res[3]])) + circuit.extend_struct_output(structs.u384(name="r4", elmts=[res[4]])) + circuit.extend_struct_output(structs.u384(name="r5", elmts=[res[5]])) + + return circuit + + +class E12TInverseCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_inverse", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # M + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + M = circuit.write_struct( + structs.E12T("M", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_inverse(M) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class E12TFrobeniusCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 1, + ): + super().__init__( + "e12t_frobenius", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # M + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + M = circuit.write_struct( + structs.E12T("M", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_frob(M) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class E12TFrobeniusSquareCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_frobenius_square", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # M + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + M = circuit.write_struct( + structs.E12T("M", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_frob_square(M) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class E12TFrobeniusCubeCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_frobenius_cube", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # M + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + M = circuit.write_struct( + structs.E12T("M", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_frob_cube(M) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class E12TCyclotomicSquareCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_cyclotomic_square", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) # M + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + M = circuit.write_struct( + structs.E12T("M", elmts=[input.pop(0) for _ in range(12)]) + ) + res = circuit.fp12_cyclotomic_square(M) + circuit.extend_struct_output(structs.E12T("res", elmts=res)) + + return circuit + + +class E12TCyclotomicSquareCompressedCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_cyclo_square_compressed", + curve_id, + auto_run, + init_hash, + compilation_mode, + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(8)]) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + xc0b1a0 = circuit.write_struct( + structs.u384(name="xc0b1a0", elmts=[input.pop(0)]) + ) + xc0b1a1 = circuit.write_struct( + structs.u384(name="xc0b1a1", elmts=[input.pop(0)]) + ) + xc0b2a0 = circuit.write_struct( + structs.u384(name="xc0b2a0", elmts=[input.pop(0)]) + ) + xc0b2a1 = circuit.write_struct( + structs.u384(name="xc0b2a1", elmts=[input.pop(0)]) + ) + xc1b0a0 = circuit.write_struct( + structs.u384(name="xc1b0a0", elmts=[input.pop(0)]) + ) + xc1b0a1 = circuit.write_struct( + structs.u384(name="xc1b0a1", elmts=[input.pop(0)]) + ) + xc1b2a0 = circuit.write_struct( + structs.u384(name="xc1b2a0", elmts=[input.pop(0)]) + ) + xc1b2a1 = circuit.write_struct( + structs.u384(name="xc1b2a1", elmts=[input.pop(0)]) + ) + res = circuit.fp12_cyclotomic_square_compressed( + [xc0b1a0, xc0b1a1], + [xc0b2a0, xc0b2a1], + [xc1b0a0, xc1b0a1], + [xc1b2a0, xc1b2a1], + ) + assert len(res) == 8 + circuit.extend_struct_output(structs.u384(name="xc0b1a0", elmts=[res[0]])) + circuit.extend_struct_output(structs.u384(name="xc0b1a1", elmts=[res[1]])) + circuit.extend_struct_output(structs.u384(name="xc0b2a0", elmts=[res[2]])) + circuit.extend_struct_output(structs.u384(name="xc0b2a1", elmts=[res[3]])) + circuit.extend_struct_output(structs.u384(name="xc1b0a0", elmts=[res[4]])) + circuit.extend_struct_output(structs.u384(name="xc1b0a1", elmts=[res[5]])) + circuit.extend_struct_output(structs.u384(name="xc1b2a0", elmts=[res[6]])) + circuit.extend_struct_output(structs.u384(name="xc1b2a1", elmts=[res[7]])) + + return circuit + + +class E12TDecompressKarabinaPtIZCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_decomp_karabina_I_Z", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(4)]) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + xc0b1a0 = circuit.write_struct( + structs.u384(name="xc0b1a0", elmts=[input.pop(0)]) + ) + xc0b1a1 = circuit.write_struct( + structs.u384(name="xc0b1a1", elmts=[input.pop(0)]) + ) + xc1b2a0 = circuit.write_struct( + structs.u384(name="xc1b2a0", elmts=[input.pop(0)]) + ) + xc1b2a1 = circuit.write_struct( + structs.u384(name="xc1b2a1", elmts=[input.pop(0)]) + ) + res = circuit.fp12_decompress_karabina_pt_I_c1b2_Z( + [xc0b1a0, xc0b1a1], [xc1b2a0, xc1b2a1] + ) + circuit.extend_struct_output(structs.u384(name="res0", elmts=[res[0]])) + circuit.extend_struct_output(structs.u384(name="res1", elmts=[res[1]])) + + return circuit + + +class E12TDecompressKarabinaPtINZCircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_decomp_karabina_I_NZ", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(8)]) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + xc0b1a0 = circuit.write_struct( + structs.u384(name="xc0b1a0", elmts=[input.pop(0)]) + ) + xc0b1a1 = circuit.write_struct( + structs.u384(name="xc0b1a1", elmts=[input.pop(0)]) + ) + xc0b2a0 = circuit.write_struct( + structs.u384(name="xc0b2a0", elmts=[input.pop(0)]) + ) + xc0b2a1 = circuit.write_struct( + structs.u384(name="xc0b2a1", elmts=[input.pop(0)]) + ) + xc1b0a0 = circuit.write_struct( + structs.u384(name="xc1b0a0", elmts=[input.pop(0)]) + ) + xc1b0a1 = circuit.write_struct( + structs.u384(name="xc1b0a1", elmts=[input.pop(0)]) + ) + xc1b2a0 = circuit.write_struct( + structs.u384(name="xc1b2a0", elmts=[input.pop(0)]) + ) + xc1b2a1 = circuit.write_struct( + structs.u384(name="xc1b2a1", elmts=[input.pop(0)]) + ) + + t0, t1 = circuit.fp12_decompress_karabina_pt_I_c1b2_NZ( + [xc0b1a0, xc0b1a1], + [xc0b2a0, xc0b2a1], + [xc1b0a0, xc1b0a1], + [xc1b2a0, xc1b2a1], + ) + circuit.extend_struct_output(structs.u384(name="t0a0", elmts=[t0[0]])) + circuit.extend_struct_output(structs.u384(name="t0a1", elmts=[t0[1]])) + circuit.extend_struct_output(structs.u384(name="t1a0", elmts=[t1[0]])) + circuit.extend_struct_output(structs.u384(name="t1a1", elmts=[t1[1]])) + + return circuit + + +class E12TDecompressKarabinaPtIICircuit(BaseEXTFCircuit): + def __init__( + self, + curve_id: int, + auto_run: bool = True, + init_hash: int = None, + compilation_mode: int = 0, + ): + super().__init__( + "e12t_decomp_karabina_II", curve_id, auto_run, init_hash, compilation_mode + ) + + def build_input(self) -> list[PyFelt]: + input = [] + input.extend([self.field.random() for _ in range(12)]) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = MillerTowerCircuit(self.name, self.curve_id, n_pairs=None) + t0a0 = circuit.write_struct(structs.u384(name="t0a0", elmts=[input.pop(0)])) + t0a1 = circuit.write_struct(structs.u384(name="t0a1", elmts=[input.pop(0)])) + t1a0 = circuit.write_struct(structs.u384(name="t1a0", elmts=[input.pop(0)])) + t1a1 = circuit.write_struct(structs.u384(name="t1a1", elmts=[input.pop(0)])) + xc0b1a0 = circuit.write_struct( + structs.u384(name="xc0b1a0", elmts=[input.pop(0)]) + ) + xc0b1a1 = circuit.write_struct( + structs.u384(name="xc0b1a1", elmts=[input.pop(0)]) + ) + xc0b2a0 = circuit.write_struct( + structs.u384(name="xc0b2a0", elmts=[input.pop(0)]) + ) + xc0b2a1 = circuit.write_struct( + structs.u384(name="xc0b2a1", elmts=[input.pop(0)]) + ) + xc1b0a0 = circuit.write_struct( + structs.u384(name="xc1b0a0", elmts=[input.pop(0)]) + ) + xc1b0a1 = circuit.write_struct( + structs.u384(name="xc1b0a1", elmts=[input.pop(0)]) + ) + xc1b2a0 = circuit.write_struct( + structs.u384(name="xc1b2a0", elmts=[input.pop(0)]) + ) + xc1b2a1 = circuit.write_struct( + structs.u384(name="xc1b2a1", elmts=[input.pop(0)]) + ) + + zc0b0, zc1b1 = circuit.fp12_decompress_karabina_pt_II( + [t0a0, t0a1], + [t1a0, t1a1], + [xc0b1a0, xc0b1a1], + [xc0b2a0, xc0b2a1], + [xc1b0a0, xc1b0a1], + [xc1b2a0, xc1b2a1], + ) + circuit.extend_struct_output(structs.u384(name="zc0b0a0", elmts=[zc0b0[0]])) + circuit.extend_struct_output(structs.u384(name="zc0b0a1", elmts=[zc0b0[1]])) + circuit.extend_struct_output(structs.u384(name="zc1b1a0", elmts=[zc1b1[0]])) + circuit.extend_struct_output(structs.u384(name="zc1b1a1", elmts=[zc1b1[1]])) + + return circuit diff --git a/hydra/garaga/precompiled_circuits/compilable_circuits/common_cairo_fustat_circuits.py b/hydra/garaga/precompiled_circuits/compilable_circuits/common_cairo_fustat_circuits.py index deb8b737..712f32fa 100644 --- a/hydra/garaga/precompiled_circuits/compilable_circuits/common_cairo_fustat_circuits.py +++ b/hydra/garaga/precompiled_circuits/compilable_circuits/common_cairo_fustat_circuits.py @@ -11,7 +11,12 @@ ModuloCircuit, PyFelt, ) -from garaga.precompiled_circuits.ec import BasicEC, ECIPCircuits, IsOnCurveCircuit +from garaga.precompiled_circuits.ec import ( + BasicEC, + BasicECG2, + ECIPCircuits, + IsOnCurveCircuit, +) class DummyCircuit(BaseModuloCircuit): @@ -168,6 +173,81 @@ def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: return circuit +class AddECPointsG2Circuit(BaseModuloCircuit): + def __init__(self, curve_id: int, auto_run: bool = True, compilation_mode: int = 0): + super().__init__( + name="add_ec_points_g2", + curve_id=curve_id, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + def build_input(self) -> list[PyFelt]: + input = [] + P = G2Point.gen_random_point(CurveID(self.curve_id)) + Q = G2Point.gen_random_point(CurveID(self.curve_id)) + input.append(self.field(P.x[0])) + input.append(self.field(P.x[1])) + input.append(self.field(P.y[0])) + input.append(self.field(P.y[1])) + input.append(self.field(Q.x[0])) + input.append(self.field(Q.x[1])) + input.append(self.field(Q.y[0])) + input.append(self.field(Q.y[1])) + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = BasicECG2( + self.name, self.curve_id, compilation_mode=self.compilation_mode + ) + px0, px1, py0, py1 = circuit.write_struct( + G2PointCircuit("p", input[0:4]), WriteOps.INPUT + ) + qx0, qx1, qy0, qy1 = circuit.write_struct( + G2PointCircuit("q", input[4:8]), WriteOps.INPUT + ) + + (nx0, nx1), (ny0, ny1) = circuit.add_points( + ((px0, px1), (py0, py1)), ((qx0, qx1), (qy0, qy1)) + ) + circuit.extend_struct_output(G2PointCircuit("result", [nx0, nx1, ny0, ny1])) + + return circuit + + +class DoubleECPointG2AEq0Circuit(BaseModuloCircuit): + def __init__(self, curve_id: int, auto_run: bool = True, compilation_mode: int = 0): + super().__init__( + name="double_ec_point_g2_a_eq_0", + curve_id=curve_id, + auto_run=auto_run, + compilation_mode=compilation_mode, + ) + + def build_input(self) -> list[PyFelt]: + input = [] + P = G2Point.gen_random_point(CurveID(self.curve_id)) + input.append(self.field(P.x[0])) + input.append(self.field(P.x[1])) + input.append(self.field(P.y[0])) + input.append(self.field(P.y[1])) + + return input + + def _run_circuit_inner(self, input: list[PyFelt]) -> ModuloCircuit: + circuit = BasicECG2( + self.name, self.curve_id, compilation_mode=self.compilation_mode + ) + px0, px1, py0, py1 = circuit.write_struct( + G2PointCircuit("p", input[0:4]), WriteOps.INPUT + ) + + (nx0, nx1), (ny0, ny1) = circuit.double_point_a_eq_0(((px0, px1), (py0, py1))) + circuit.extend_struct_output(G2PointCircuit("result", [nx0, nx1, ny0, ny1])) + + return circuit + + class SlopeInterceptSamePointCircuit(BaseModuloCircuit): def __init__( self, curve_id: int, auto_run: bool = True, compilation_mode: int = 0 diff --git a/hydra/garaga/precompiled_circuits/ec.py b/hydra/garaga/precompiled_circuits/ec.py index 674234a0..1c9266ae 100644 --- a/hydra/garaga/precompiled_circuits/ec.py +++ b/hydra/garaga/precompiled_circuits/ec.py @@ -2,6 +2,7 @@ from garaga.definitions import CURVES from garaga.extension_field_modulo_circuit import ( + ExtensionFieldModuloCircuit, ModuloCircuit, ModuloCircuitElement, PyFelt, @@ -544,7 +545,7 @@ def double_point( slope = self._compute_doubling_slope(P, A) slope_sqr = self.mul(slope, slope) nx = self.sub(self.sub(slope_sqr, xP), xP) - ny = self.sub(yP, self.mul(slope, self.sub(xP, nx))) + ny = self.sub(self.mul(slope, self.sub(xP, nx)), yP) return (nx, ny) def scalar_mul_2_pow_k( @@ -593,3 +594,69 @@ def _is_on_curve_G2_weirstrass( x3_ax_b = [self.add(x3[0], ax_b[0]), self.add(x3[1], ax_b[1])] return y2, x3_ax_b + + +class BasicECG2(ExtensionFieldModuloCircuit): + def __init__(self, name: str, curve_id: int, compilation_mode: int = 0): + super().__init__( + name=name, + curve_id=curve_id, + extension_degree=2, + generic_circuit=True, + compilation_mode=compilation_mode, + ) + self.curve = CURVES[curve_id] + + def _compute_adding_slope( + self, + P: tuple[ + tuple[ModuloCircuitElement, ModuloCircuitElement], + tuple[ModuloCircuitElement, ModuloCircuitElement], + ], + Q: tuple[ + tuple[ModuloCircuitElement, ModuloCircuitElement], + tuple[ModuloCircuitElement, ModuloCircuitElement], + ], + ): + xP, yP = P + xQ, yQ = Q + slope = self.fp2_div(self.extf_sub(yP, yQ), self.extf_sub(xP, xQ)) + return slope + + def _compute_doubling_slope_a_eq_0( + self, + P: tuple[ModuloCircuitElement, ModuloCircuitElement], + ): + + xP, yP = P + # Compute doubling slope m = (3x^2 + A) / 2y + three = self.set_or_get_constant(self.field(3)) + + m_num = self.extf_scalar_mul(self.fp2_square(xP), three) + m_den = self.extf_add(yP, yP) + m = self.fp2_div(m_num, m_den) + return m + + def add_points( + self, + P: tuple[ModuloCircuitElement, ModuloCircuitElement], + Q: tuple[ModuloCircuitElement, ModuloCircuitElement], + ) -> tuple[ModuloCircuitElement, ModuloCircuitElement]: + xP, yP = P + xQ, yQ = Q + slope = self._compute_adding_slope(P, Q) + slope_sqr = self.fp2_square(slope) + nx = self.extf_sub(self.extf_sub(slope_sqr, xP), xQ) + ny = self.extf_sub(self.fp2_mul(slope, self.extf_sub(xP, nx)), yP) + return (nx, ny) + + def double_point_a_eq_0( + self, + P: tuple[ModuloCircuitElement, ModuloCircuitElement], + ) -> tuple[ModuloCircuitElement, ModuloCircuitElement]: + xP, yP = P + slope = self._compute_doubling_slope_a_eq_0(P) + slope_sqr = self.fp2_square(slope) + nx = self.extf_sub(self.extf_sub(slope_sqr, xP), xP) + ny = self.extf_sub(self.fp2_mul(slope, self.extf_sub(xP, nx)), yP) + return (nx, ny) diff --git a/hydra/garaga/precompiled_circuits/miller_tower.py b/hydra/garaga/precompiled_circuits/miller_tower.py new file mode 100644 index 00000000..a94a5dca --- /dev/null +++ b/hydra/garaga/precompiled_circuits/miller_tower.py @@ -0,0 +1,620 @@ +from typing import Iterator + +from garaga.definitions import BLS12_381_ID, BN254_ID, CURVES +from garaga.extension_field_modulo_circuit import ModuloCircuitElement +from garaga.precompiled_circuits.multi_miller_loop import MultiMillerLoopCircuit + + +def tower_line_function_sparsity(curve_id: int) -> list[int]: + match curve_id: + case 0: + return [2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0] + case 1: + return [1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0] + case _: + raise ValueError(f"Invalid curve ID: {curve_id}") + + +class MillerTowerCircuit(MultiMillerLoopCircuit): + def __init__( + self, + name: str, + curve_id: int, + n_pairs: int, + compilation_mode: int = 1, + ): + super().__init__( + name=name, + curve_id=curve_id, + n_pairs=n_pairs, + compilation_mode=compilation_mode, + ) + + def eval_tower_line(self, line: Iterator[ModuloCircuitElement], yInv, xNegOverY): + assert len(line) == 4 + # Input is R0 = slope, R1 = intercept + r0 = [line[0], line[1]] + r1 = [line[2], line[3]] + if self.curve_id == BN254_ID: + return [ + self.mul(r0[0], xNegOverY), + self.mul(r0[1], xNegOverY), + self.mul(r1[0], yInv), + self.mul(r1[1], yInv), + ] + elif self.curve_id == BLS12_381_ID: + return [ + self.mul(r1[0], yInv), + self.mul(r1[1], yInv), + self.mul(r0[0], xNegOverY), + self.mul(r0[1], xNegOverY), + ] + else: + raise NotImplementedError + + def mul_by_line_tower( + self, + tower_fp12: list[ModuloCircuitElement], + line_evaluated: list[ModuloCircuitElement], + ): + assert len(tower_fp12) == 12 + assert ( + len(line_evaluated) == 4 + ), f"Expected 4 elements, got {len(line_evaluated)}" + c0_fp6, c1_fp6 = tower_fp12[0:6], tower_fp12[6:12] + # c0_b0, c0_b1, c0_b2 = c0[0:2], c0[2:4], c0[4:6] + # c1_b0, c1_b1, c1_b2 = c1[0:2], c1[2:4], c1[4:6] + + # MulBy34. multiplication by sparse element (1,0,0,c3,c4,0) + if self.curve_id == 0: + a = c0_fp6 + b = c1_fp6 + c3, c4 = line_evaluated[0:2], line_evaluated[2:4] + b = self._fp6_by_01(b, c3, c4) + + d0 = self.extf_add( + [self.set_or_get_constant(1), self.set_or_get_constant(0)], c3 + ) + d = self.extf_add(c0_fp6, c1_fp6) + d = self._fp6_by_01(d, d0, c4) + + z_c1 = self.extf_add(self.extf_neg(self.extf_add(a, b)), d) + z_c0 = self.extf_add(self.fp6_mul_by_non_residue(b), a) + + return z_c0 + z_c1 + elif self.curve_id == 1: + # Mul By 01 + # // MulBy01 multiplication by sparse element (c0, c1, 0, 0, 1) + # func (z *E12) MulBy01(c0, c1 *E2) *E12 { + + # var a, b E6 + # var d E2 + + # a.Set(&z.C0) + # a.MulBy01(c0, c1) + + # b.MulByNonResidue(&z.C1) + # d.SetOne().Add(c1, &d) + + # z.C1.Add(&z.C1, &z.C0) + # z.C1.MulBy01(c0, &d) + # z.C1.Sub(&z.C1, &a) + # z.C1.Sub(&z.C1, &b) + # z.C0.MulByNonResidue(&b) + # z.C0.Add(&z.C0, &a) + + # return z + # } + c0, c1 = line_evaluated[0:2], line_evaluated[2:4] + + a = c0_fp6 + a = self._fp6_by_01(a, c0, c1) + b = self.fp6_mul_by_non_residue(c1_fp6) + + d = [self.add(self.set_or_get_constant(1), c1[0]), c1[1]] + + z_c1 = self.extf_add(c1_fp6, c0_fp6) + z_c1 = self._fp6_by_01(z_c1, c0, d) + z_c1 = self.extf_sub(z_c1, a) + z_c1 = self.extf_sub(z_c1, b) + + z_c0 = self.fp6_mul_by_non_residue(b) + z_c0 = self.extf_add(z_c0, a) + return z_c0 + z_c1 + + def mul_by_line_line_tower(self, tower_fp12, line_line): + assert len(tower_fp12) == 12 + assert len(line_line) == 10 + c0_fp6, c1_fp6 = tower_fp12[0:6], tower_fp12[6:12] + + def mul_line_by_line_tower(self, l1, l2): + assert len(l1) == 4 + assert len(l2) == 4 + if self.curve_id == 0: + d3, d4 = l1[0:2], l1[2:4] + c3, c4 = l2[0:2], l2[2:4] + + x3 = self.fp2_mul(c3, d3) + x4 = self.fp2_mul(c4, d4) + x04 = self.extf_add(c4, d4) + x03 = self.extf_add(c3, d3) + tmp = self.extf_add(c3, c4) + x34 = self.extf_sub( + self.extf_sub(self.fp2_mul(self.extf_add(d3, d4), tmp), x3), x4 + ) + z00 = self.fp2_mul_by_non_residue(x4) + z00 = [self.add(z00[0], self.set_or_get_constant(1)), z00[1]] + + return z00 + x3 + x34 + x03 + x04 + if self.curve_id == 1: + + c0, c1 = l2[0:2], l2[2:4] + d0, d1 = l1[0:2], l1[2:4] + + x0 = self.fp2_mul(c0, d0) + x1 = self.fp2_mul(c1, d1) + + x04 = self.extf_add(d0, c0) + tmp = self.extf_add(c0, c1) + x01 = self.extf_sub( + self.extf_sub(self.fp2_mul(self.extf_add(d0, d1), tmp), x0), x1 + ) + x14 = self.extf_add(d1, c1) + z00 = self.fp2_mul_by_non_residue( + [self.set_or_get_constant(1), self.set_or_get_constant(0)] + ) + z00 = self.extf_add(z00, x0) + + # C0B0 + C0B1 + C0B2 + C1B1 + C1B2 + return z00 + x01 + x1 + x04 + x14 + + def _fp6_by_01(self, e6: list[ModuloCircuitElement], c0, c1): + assert len(e6) == 6 + assert len(c0) == 2 + assert len(c1) == 2 + b0, b1, b2 = e6[0:2], e6[2:4], e6[4:6] + a = self.fp2_mul(b0, c0) + b = self.fp2_mul(b1, c1) + tmp = self.extf_add(b1, b2) + t0 = self.fp2_mul(c1, tmp) + t0 = self.extf_sub(t0, b) + t0 = self.fp2_mul_by_non_residue(t0) + t0 = self.extf_add(t0, a) + + tmp = self.extf_add(b0, b2) + t2 = self.fp2_mul(c0, tmp) + t2 = self.extf_sub(t2, a) + t2 = self.extf_add(t2, b) + + t1 = self.extf_add(c0, c1) + tmp = self.extf_add(b0, b1) + t1 = self.fp2_mul(t1, tmp) + t1 = self.extf_sub(t1, a) + t1 = self.extf_sub(t1, b) + + b0 = t0 + b1 = t1 + b2 = t2 + # flatten lists: + return b0 + b1 + b2 + + def fp6_mul_by_non_residue(self, a: list[ModuloCircuitElement]): + assert len(a) == 6 + a = list(a) + b0, b1, b2 = a[0:2], a[2:4], a[4:6] + return self.fp2_mul_by_non_residue(b2) + b0 + b1 + + def fp12_square(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + + xc0, xc1 = a[0:6], a[6:12] + c0 = self.extf_sub(xc0, xc1) + c3 = self.extf_add(xc0, self.extf_neg(self.fp6_mul_by_non_residue(xc1))) + c2 = self.fp6_mul(xc0, xc1) + c0 = self.extf_add(self.fp6_mul(c0, c3), c2) + z_c1 = self.extf_add(c2, c2) + z_c0 = self.extf_add(c0, self.fp6_mul_by_non_residue(c2)) + + return z_c0 + z_c1 + + def fp12_mul(self, x: list[ModuloCircuitElement], y: list[ModuloCircuitElement]): + assert len(x) == 12 + assert len(y) == 12 + + x_c0, x_c1 = x[0:6], x[6:12] + y_c0, y_c1 = y[0:6], y[6:12] + + a = self.extf_add(x_c0, x_c1) + b = self.extf_add(y_c0, y_c1) + a = self.fp6_mul(a, b) + b = self.fp6_mul(x_c0, y_c0) + c = self.fp6_mul(x_c1, y_c1) + z_c1 = self.extf_sub(a, b) + z_c1 = self.extf_sub(z_c1, c) + z_c0 = self.fp6_mul_by_non_residue(c) + z_c0 = self.extf_add(z_c0, b) + + return z_c0 + z_c1 + + def fp6_mul(self, a: list[ModuloCircuitElement], b: list[ModuloCircuitElement]): + assert len(a) == 6 + assert len(b) == 6 + + xb0, xb1, xb2 = a[0:2], a[2:4], a[4:6] + yb0, yb1, yb2 = b[0:2], b[2:4], b[4:6] + + t0 = self.fp2_mul(xb0, yb0) + t1 = self.fp2_mul(xb1, yb1) + t2 = self.fp2_mul(xb2, yb2) + + c0 = self.extf_add(xb1, xb2) + tmp = self.extf_add(yb1, yb2) + + c0 = self.extf_add( + self.fp2_mul_by_non_residue( + self.extf_sub(self.extf_sub(self.fp2_mul(c0, tmp), t1), t2) + ), + t0, + ) + + c1 = self.extf_add(xb0, xb1) + tmp = self.extf_add(yb0, yb1) + c1 = self.extf_sub(self.extf_sub(self.fp2_mul(c1, tmp), t0), t1) + tmp = self.fp2_mul_by_non_residue(t2) + c1 = self.extf_add(c1, tmp) + + tmp = self.extf_add(xb0, xb2) + c2 = self.extf_add( + self.extf_sub( + self.extf_sub(self.fp2_mul(self.extf_add(yb0, yb2), tmp), t0), t2 + ), + t1, + ) + + return c0 + c1 + c2 + + def fp12_inverse(self, a: list[ModuloCircuitElement]): + + assert len(a) == 12 + + xc0, xc1 = a[0:6], a[6:12] + + t0 = self.fp6_square(xc0) + t1 = self.fp6_square(xc1) + tmp = self.fp6_mul_by_non_residue(t1) + t0 = self.extf_sub(t0, tmp) + t1 = self.fp6_inverse(t0) + z_c0 = self.fp6_mul(xc0, t1) + z_c1 = self.fp6_mul(xc1, t1) + z_c1 = self.extf_neg(z_c1) + + return z_c0 + z_c1 + + def fp6_inverse(self, a: list[ModuloCircuitElement]): + assert len(a) == 6 + # func (z *E6) Inverse(x *E6) *E6 { + # // Algorithm 17 from https://eprint.iacr.org/2010/354.pdf + # // step 9 is wrong in the paper it's t1-t4 + # var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 E2 + # t0.Square(&x.B0) + # t1.Square(&x.B1) + # t2.Square(&x.B2) + # t3.Mul(&x.B0, &x.B1) + # t4.Mul(&x.B0, &x.B2) + # t5.Mul(&x.B1, &x.B2) + # c0.MulByNonResidue(&t5).Neg(&c0).Add(&c0, &t0) + # c1.MulByNonResidue(&t2).Sub(&c1, &t3) + # c2.Sub(&t1, &t4) + # t6.Mul(&x.B0, &c0) + # d1.Mul(&x.B2, &c1) + # d2.Mul(&x.B1, &c2) + # d1.Add(&d1, &d2).MulByNonResidue(&d1) + # t6.Add(&t6, &d1) + # t6.Inverse(&t6) + # z.B0.Mul(&c0, &t6) + # z.B1.Mul(&c1, &t6) + # z.B2.Mul(&c2, &t6) + xb0, xb1, xb2 = a[0:2], a[2:4], a[4:6] + t0 = self.fp2_square(xb0) + t1 = self.fp2_square(xb1) + t2 = self.fp2_square(xb2) + + t3 = self.fp2_mul(xb0, xb1) + t4 = self.fp2_mul(xb0, xb2) + t5 = self.fp2_mul(xb1, xb2) + c0 = self.extf_add(self.extf_neg(self.fp2_mul_by_non_residue(t5)), t0) + c1 = self.extf_sub(self.fp2_mul_by_non_residue(t2), t3) + c2 = self.extf_sub(t1, t4) + + t6 = self.fp2_mul(xb0, c0) + d1 = self.fp2_mul(xb2, c1) + d2 = self.fp2_mul(xb1, c2) + d1 = self.fp2_mul_by_non_residue(self.extf_add(d1, d2)) + t6 = self.extf_add(t6, d1) + t6 = self.fp2_inv(t6) + zb0 = self.fp2_mul(c0, t6) + zb1 = self.fp2_mul(c1, t6) + zb2 = self.fp2_mul(c2, t6) + + return zb0 + zb1 + zb2 + + def fp6_square(self, a: list[ModuloCircuitElement]): + assert len(a) == 6 + + xb0, xb1, xb2 = a[0:2], a[2:4], a[4:6] + c4 = self.fp2_mul(xb0, xb1) + c4 = self.extf_add(c4, c4) + c5 = self.fp2_square(xb2) + c1 = self.extf_add(self.fp2_mul_by_non_residue(c5), c4) + c2 = self.extf_sub(c4, c5) + c3 = self.fp2_square(xb0) + c4 = self.extf_add(self.extf_sub(xb0, xb1), xb2) + c5 = self.fp2_mul(xb1, xb2) + c5 = self.extf_add(c5, c5) + + c4 = self.fp2_square(c4) + c0 = self.extf_add(self.fp2_mul_by_non_residue(c5), c3) + zb2 = self.extf_sub(self.extf_add(self.extf_add(c2, c4), c5), c3) + zb0 = c0 + zb1 = c1 + + return zb0 + zb1 + zb2 + + def fp12_conjugate(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + + raise NotImplementedError("Not implemented") + + def fp12_cyclotomic_square(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + + xc0, xc1 = a[0:6], a[6:12] + xc0b0 = xc0[0:2] + xc0b1 = xc0[2:4] + xc0b2 = xc0[4:6] + xc1b0 = xc1[0:2] + xc1b1 = xc1[2:4] + xc1b2 = xc1[4:6] + + t0 = self.fp2_square(xc1b1) + t1 = self.fp2_square(xc0b0) + t6 = self.extf_add(xc1b1, xc0b0) + t6 = self.fp2_square(t6) + t6 = self.extf_sub(t6, t0) + t6 = self.extf_sub(t6, t1) + t2 = self.fp2_square(xc0b2) + t3 = self.fp2_square(xc1b0) + t7 = self.extf_add(xc0b2, xc1b0) + t7 = self.fp2_square(t7) + t7 = self.extf_sub(t7, t2) + t7 = self.extf_sub(t7, t3) + + t4 = self.fp2_square(xc1b2) + t5 = self.fp2_square(xc0b1) + t8 = self.extf_add(xc1b2, xc0b1) + t8 = self.fp2_square(t8) + t8 = self.extf_sub(t8, t4) + t8 = self.extf_sub(t8, t5) + t8 = self.fp2_mul_by_non_residue(t8) + + t0 = self.fp2_mul_by_non_residue(t0) + t0 = self.extf_add(t0, t1) + t2 = self.fp2_mul_by_non_residue(t2) + t2 = self.extf_add(t2, t3) + t4 = self.fp2_mul_by_non_residue(t4) + t4 = self.extf_add(t4, t5) + + zc0b0 = self.extf_sub(t0, xc0b0) + zc0b0 = self.extf_add(zc0b0, zc0b0) + zc0b0 = self.extf_add(zc0b0, t0) + + zc0b1 = self.extf_sub(t2, xc0b1) + zc0b1 = self.extf_add(zc0b1, zc0b1) + zc0b1 = self.extf_add(zc0b1, t2) + + zc0b2 = self.extf_sub(t4, xc0b2) + zc0b2 = self.extf_add(zc0b2, zc0b2) + zc0b2 = self.extf_add(zc0b2, t4) + + zc1b0 = self.extf_add(t8, xc1b0) + zc1b0 = self.extf_add(zc1b0, zc1b0) + zc1b0 = self.extf_add(zc1b0, t8) + + zc1b1 = self.extf_add(t6, xc1b1) + zc1b1 = self.extf_add(zc1b1, zc1b1) + zc1b1 = self.extf_add(zc1b1, t6) + + zc1b2 = self.extf_add(t7, xc1b2) + zc1b2 = self.extf_add(zc1b2, zc1b2) + zc1b2 = self.extf_add(zc1b2, t7) + + return zc0b0 + zc0b1 + zc0b2 + zc1b0 + zc1b1 + zc1b2 + + def fp2_conjugate(self, a: list[ModuloCircuitElement]): + assert len(a) == 2 + return [a[0], self.neg(a[1])] + + def mul_by_non_residue_k_power_n( + self, x: list[ModuloCircuitElement], k: int, n: int + ): + from garaga.hints.tower_backup import E2 + + assert len(x) == 2 + curve = CURVES[self.curve_id] + non_residue = E2(curve.nr_a0, curve.nr_a1, curve.p) + # nr^(n*(p^k-1)/6) + res: E2 = non_residue ** ((n * (curve.p**k - 1) // 6)) + if res.a1 != 0: + factor = [ + self.set_or_get_constant(res.a0), + self.set_or_get_constant(res.a1), + ] + return self.fp2_mul(factor, x) + else: + factor = self.set_or_get_constant(res.a0) + return [self.mul(factor, x[0]), self.mul(factor, x[1])] + + def fp12_frob(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + + c0b0 = self.fp2_conjugate(a[0:2]) + c0b0[0] = self.add( + c0b0[0], self.set_or_get_constant(0) + ) # Input cannot be output. # TODO: Make a manual circuit or something better. + c0b1 = self.fp2_conjugate(a[2:4]) + c0b2 = self.fp2_conjugate(a[4:6]) + c1b0 = self.fp2_conjugate(a[6:8]) + c1b1 = self.fp2_conjugate(a[8:10]) + c1b2 = self.fp2_conjugate(a[10:12]) + + c0b1 = self.mul_by_non_residue_k_power_n(c0b1, 1, 2) + c0b2 = self.mul_by_non_residue_k_power_n(c0b2, 1, 4) + c1b0 = self.mul_by_non_residue_k_power_n(c1b0, 1, 1) + c1b1 = self.mul_by_non_residue_k_power_n(c1b1, 1, 3) + c1b2 = self.mul_by_non_residue_k_power_n(c1b2, 1, 5) + + return c0b0 + c0b1 + c0b2 + c1b0 + c1b1 + c1b2 + + def fp12_frob_square(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + c0b0 = [ + self.add(a[0], self.set_or_get_constant(0)), + self.add(a[1], self.set_or_get_constant(0)), + ] # Input cannot be output. # TODO: Make a manual circuit or something better. + c0b1 = self.mul_by_non_residue_k_power_n(a[2:4], 2, 2) + c0b2 = self.mul_by_non_residue_k_power_n(a[4:6], 2, 4) + c1b0 = self.mul_by_non_residue_k_power_n(a[6:8], 2, 1) + c1b1 = self.mul_by_non_residue_k_power_n(a[8:10], 2, 3) + c1b2 = self.mul_by_non_residue_k_power_n(a[10:12], 2, 5) + + return c0b0 + c0b1 + c0b2 + c1b0 + c1b1 + c1b2 + + def fp12_frob_cube(self, a: list[ModuloCircuitElement]): + assert len(a) == 12 + + c0b0 = self.fp2_conjugate(a[0:2]) + c0b0[0] = self.add( + c0b0[0], self.set_or_get_constant(0) + ) # Input cannot be output. # TODO: Make a manual circuit or something better. + c0b1 = self.fp2_conjugate(a[2:4]) + c0b2 = self.fp2_conjugate(a[4:6]) + c1b0 = self.fp2_conjugate(a[6:8]) + c1b1 = self.fp2_conjugate(a[8:10]) + c1b2 = self.fp2_conjugate(a[10:12]) + + c0b1 = self.mul_by_non_residue_k_power_n(c0b1, 3, 2) + c0b2 = self.mul_by_non_residue_k_power_n(c0b2, 3, 4) + c1b0 = self.mul_by_non_residue_k_power_n(c1b0, 3, 1) + c1b1 = self.mul_by_non_residue_k_power_n(c1b1, 3, 3) + c1b2 = self.mul_by_non_residue_k_power_n(c1b2, 3, 5) + + return c0b0 + c0b1 + c0b2 + c1b0 + c1b1 + c1b2 + + def fp12_cyclotomic_square_compressed( + self, + xc0b1: list[ModuloCircuitElement], + xc0b2: list[ModuloCircuitElement], + xc1b0: list[ModuloCircuitElement], + xc1b2: list[ModuloCircuitElement], + ): + assert len(xc0b1) == len(xc0b2) == len(xc1b0) == len(xc1b2) == 2 + + t0 = self.fp2_square(xc0b1) + t1 = self.fp2_square(xc1b2) + t5 = self.extf_add(xc0b1, xc1b2) + t2 = self.fp2_square(t5) + + t3 = self.extf_add(t0, t1) + t5 = self.extf_sub(t2, t3) + + t6 = self.extf_add(xc1b0, xc0b2) + t3 = self.fp2_square(t6) + t2 = self.fp2_square(xc1b0) + + t6 = self.fp2_mul_by_non_residue(t5) + t5 = self.extf_add(t6, xc1b0) + t5 = self.extf_add(t5, t5) + + zc1b0 = self.extf_add(t5, t6) + + t4 = self.fp2_mul_by_non_residue(t1) + t5 = self.extf_add(t0, t4) + t6 = self.extf_sub(t5, xc0b2) + + t1 = self.fp2_square(xc0b2) + t6 = self.extf_add(t6, t6) + zc0b2 = self.extf_add(t6, t5) + + t4 = self.fp2_mul_by_non_residue(t1) + t5 = self.extf_add(t2, t4) + t6 = self.extf_sub(t5, xc0b1) + t6 = self.extf_add(t6, t6) + zc0b1 = self.extf_add(t6, t5) + + t0 = self.extf_add(t2, t1) + t5 = self.extf_sub(t3, t0) + t6 = self.extf_add(t5, xc1b2) + t6 = self.extf_add(t6, t6) + zc1b2 = self.extf_add(t5, t6) + + return zc0b1 + zc0b2 + zc1b0 + zc1b2 + + def fp12_decompress_karabina_pt_I_c1b2_Z(self, xc0b1, xc1b2): + + assert len(xc0b1) == len(xc1b2) == 2 + + t0 = self.fp2_mul(xc0b1, xc1b2) + t0 = self.extf_add(t0, t0) + + # t1 = xc0b2 + + return t0 + + def fp12_decompress_karabina_pt_I_c1b2_NZ( + self, + xc0b1: list[ModuloCircuitElement], + xc0b2: list[ModuloCircuitElement], + xc1b0: list[ModuloCircuitElement], + xc1b2: list[ModuloCircuitElement], + ): + assert len(xc0b1) == len(xc0b2) == len(xc1b0) == len(xc1b2) == 2 + + t0 = self.fp2_square(xc0b1) + t1 = self.extf_sub(t0, xc0b2) + t1 = self.extf_add(t1, t1) + t1 = self.extf_add(t1, t0) + + t2 = self.fp2_square(xc1b2) + t0 = self.extf_add(self.fp2_mul_by_non_residue(t2), t1) + t1 = self.extf_add(xc1b0, xc1b0) + t1 = self.extf_add(t1, t1) + + return t0, t1 + + def fp12_decompress_karabina_pt_II( + self, + t0: list[ModuloCircuitElement], + t1: list[ModuloCircuitElement], + xc0b1: list[ModuloCircuitElement], + xc0b2: list[ModuloCircuitElement], + xc1b0: list[ModuloCircuitElement], + xc1b2: list[ModuloCircuitElement], + ): + assert len(t0) == len(t1) == 2 + assert len(xc0b1) == len(xc0b2) == len(xc1b0) == len(xc1b2) == 2 + + zc1b1 = self.fp2_div(t0, t1) + + t1 = self.fp2_mul(xc0b2, xc0b1) + t2 = self.extf_sub(self.fp2_square(zc1b1), t1) + t2 = self.extf_add(t2, t2) + t2 = self.extf_sub(t2, t1) + t1 = self.fp2_mul(xc1b0, xc1b2) + t2 = self.extf_add(t2, t1) + zc0b0 = self.fp2_mul_by_non_residue(t2) + zc0b0 = [ + self.add(zc0b0[0], self.set_or_get_constant(1)), + zc0b0[1], + ] + + return zc0b0, zc1b1 diff --git a/hydra/garaga/precompiled_circuits/multi_miller_loop.py b/hydra/garaga/precompiled_circuits/multi_miller_loop.py index c4bd0425..9afd1d65 100644 --- a/hydra/garaga/precompiled_circuits/multi_miller_loop.py +++ b/hydra/garaga/precompiled_circuits/multi_miller_loop.py @@ -28,6 +28,7 @@ def __init__( compilation_mode: int = 0, precompute_lines: bool = False, n_points_precomputed_lines: int = None, + tower_mode: bool = False, ): super().__init__( name=name, diff --git a/hydra/garaga/starknet/groth16_contract_generator/generator.py b/hydra/garaga/starknet/groth16_contract_generator/generator.py index 0c34f93d..3cd13077 100644 --- a/hydra/garaga/starknet/groth16_contract_generator/generator.py +++ b/hydra/garaga/starknet/groth16_contract_generator/generator.py @@ -8,7 +8,7 @@ from garaga.starknet.cli.utils import create_directory, get_package_version from garaga.starknet.groth16_contract_generator.parsing_utils import Groth16VerifyingKey -ECIP_OPS_CLASS_HASH = 0x2672F1F079CCBAFE1BE4A20A76421B509FCFB406CBF6818563ED812EDAEB3A3 +ECIP_OPS_CLASS_HASH = 0x70C1D1C709C75E3CF51D79D19CF7C84A0D4521F3A2B8BF7BFF5CB45EE0DD289 def precompute_lines_from_vk(vk: Groth16VerifyingKey) -> StructArray: @@ -73,7 +73,8 @@ def gen_groth16_verifier( use starknet::SyscallResultTrait; use garaga::definitions::{{G1Point, G1G2Pair}}; use garaga::groth16::{{multi_pairing_check_{curve_id.name.lower()}_3P_2F_with_extra_miller_loop_result}}; - use garaga::ec_ops::{{G1PointTrait, G2PointTrait, ec_safe_add}}; + use garaga::ec_ops::{{G1PointTrait, ec_safe_add}}; + use garaga::ec_ops_g2::{{G2PointTrait}}; use garaga::utils::calldata::{{deserialize_full_proof_with_hints_{curve_id.name.lower()}}}; use super::{{N_PUBLIC_INPUTS, vk, ic, precomputed_lines}}; @@ -158,7 +159,7 @@ def gen_groth16_verifier( create_directory(src_dir) with open(os.path.join(output_folder_path, ".tools-versions"), "w") as f: - f.write("scarb 2.8.2\n") + f.write("scarb 2.8.4\n") with open(os.path.join(src_dir, "groth16_verifier_constants.cairo"), "w") as f: f.write(constants_code) @@ -198,7 +199,7 @@ def get_scarb_toml_file(package_name: str, cli_mode: bool): [dependencies] garaga = {{ {dep} }} -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/hydra/garaga/starknet/groth16_contract_generator/generator_risc0.py b/hydra/garaga/starknet/groth16_contract_generator/generator_risc0.py index 6e5b65a6..1845333f 100644 --- a/hydra/garaga/starknet/groth16_contract_generator/generator_risc0.py +++ b/hydra/garaga/starknet/groth16_contract_generator/generator_risc0.py @@ -70,7 +70,8 @@ def gen_risc0_groth16_verifier( use starknet::SyscallResultTrait; use garaga::definitions::{{G1Point, G1G2Pair}}; use garaga::groth16::{{multi_pairing_check_{curve_id.name.lower()}_3P_2F_with_extra_miller_loop_result}}; - use garaga::ec_ops::{{G1PointTrait, G2PointTrait, ec_safe_add}}; + use garaga::ec_ops::{{G1PointTrait, ec_safe_add}}; + use garaga::ec_ops_g2::{{G2PointTrait}}; use garaga::utils::risc0::{{compute_receipt_claim, journal_sha256}}; use garaga::utils::calldata::deserialize_full_proof_with_hints_risc0; use super::{{N_FREE_PUBLIC_INPUTS, vk, ic, precomputed_lines, T}}; diff --git a/hydra/garaga/starknet/tests_and_calldata_generators/drand_calldata.py b/hydra/garaga/starknet/tests_and_calldata_generators/drand_calldata.py index dbac2947..17ecbfdd 100644 --- a/hydra/garaga/starknet/tests_and_calldata_generators/drand_calldata.py +++ b/hydra/garaga/starknet/tests_and_calldata_generators/drand_calldata.py @@ -24,26 +24,7 @@ def drand_round_to_calldata(round_number: int) -> list[int]: round = get_randomness(chain.hash, round_number) - ######################################## - # Temp fix before we figure out what the hell is wrong with G2 compress Deserialization sign. - check = ( - G1G2Pair.pair( - [ - G1G2Pair( - p=round.signature_point, q=G2Point.get_nG(CurveID.BLS12_381, 1) - ), - G1G2Pair(p=msg_point, q=-chain.public_key), - ], - curve_id=CurveID.BLS12_381, - ).value_coeffs - == [1] + [0] * 11 - ) - - if not check: - sig_pt = -round.signature_point - else: - sig_pt = round.signature_point - + sig_pt = round.signature_point ################### mpc_builder = MPCheckCalldataBuilder( curve_id=CurveID.BLS12_381, diff --git a/hydra/garaga/starknet/tests_and_calldata_generators/test_writer.py b/hydra/garaga/starknet/tests_and_calldata_generators/test_writer.py index e7f62432..71e7cd57 100644 --- a/hydra/garaga/starknet/tests_and_calldata_generators/test_writer.py +++ b/hydra/garaga/starknet/tests_and_calldata_generators/test_writer.py @@ -2,7 +2,15 @@ import random import subprocess -from garaga.definitions import CURVES, CurveID, G1Point +import garaga.modulo_circuit_structs as structs +from garaga.definitions import ( + CURVES, + CurveID, + G1G2Pair, + G1Point, + G2Point, + get_base_field, +) from garaga.precompiled_circuits.multi_pairing_check import get_pairing_check_input from garaga.starknet.cli.utils import create_directory from garaga.starknet.tests_and_calldata_generators.mpcheck import MPCheckCalldataBuilder @@ -54,9 +62,138 @@ def generate_msm_test_edge_cases(curve_id, n_points, seed): ) +def generate_tower_pairing_test(curve_id, n_pairs, seed): + random.seed(seed) + pairs: list[G1G2Pair] + if n_pairs == 1: + pairs = [ + G1G2Pair( + p=G1Point.get_nG(curve_id, 1), + q=G2Point.get_nG(curve_id, 1), + ) + ] + else: + pairs, _ = get_pairing_check_input( + curve_id=curve_id, n_pairs=n_pairs, return_pairs=True + ) + + res = G1G2Pair.pair(pairs, curve_id) + res = res.felt_coeffs + e12t = structs.E12T(name="expected_result", elmts=res) + i_s = list(range(n_pairs)) + code = f""" +#[test] +fn test_tower_pairing_{curve_id.name}_{n_pairs}P() {{ + let mut res:E12T = E12TOne::one(); +""" + for i, pair in enumerate(pairs): + code += f""" + {structs.G1PointCircuit.from_G1Point(f"p{i}", pair.p).serialize()} + p{i}.assert_on_curve({curve_id.value}); + {structs.G2PointCircuit.from_G2Point(f"q{i}", pair.q).serialize()} + q{i}.assert_on_curve({curve_id.value}); + let (tmp{i}) = miller_loop_{pair.p.curve_id.name.lower()}_tower(p{i}, q{i}); + let (res) = run_{pair.p.curve_id.name.upper()}_E12T_MUL_circuit(tmp{i}, res);""" + code += f""" + let final = final_exp_{curve_id.name.lower()}_tower(res); + assert_eq!(final, {e12t.serialize(raw=True)}); +}} +""" + return code + + +def generate_tower_final_exp_test(curve_id, seed): + from garaga.hints.tower_backup import E12 + + random.seed(seed) + field = get_base_field(curve_id) + elmts = [field.random() for _ in range(12)] + e12 = E12(elmts, curve_id.value) + e12t = structs.E12T(name="input", elmts=elmts) + cofactor = CURVES[curve_id.value].final_exp_cofactor + h = cofactor * (CURVES[curve_id.value].p ** 12 - 1) // CURVES[curve_id.value].n + expected = structs.E12T(name="expected", elmts=(e12**h).felt_coeffs) + code = f""" +#[test] +fn test_tower_final_exp_{curve_id.name}() {{ + {e12t.serialize()} + let res = final_exp_{curve_id.name.lower()}_tower(input); + assert_eq!(res, {expected.serialize(raw=True)}); +}} +""" + return code + + +def generate_expt_half_test(curve_id, seed): + from garaga.hints.tower_backup import E12 + + random.seed(seed) + field = get_base_field(curve_id) + elmts = [field.random() for _ in range(12)] + + e12 = E12(elmts, curve_id.value) + # Simulate easy part : + p = CURVES[curve_id.value].p + e12 = e12 ** ((p**6 - 1) * (p**2 + 1)) + e12t = structs.E12T(name="input", elmts=e12.felt_coeffs) + + h = 7566188111470821376 + + expected_tower = e12**h + assert expected_tower.conjugate() == expected_tower.__inv__() + expected = structs.E12T( + name="expected", elmts=expected_tower.conjugate().felt_coeffs + ) + code = f""" +#[test] +fn test_expt_half_{curve_id.name}() {{ + {e12t.serialize()} + let (res) = expt_half_{curve_id.name.lower()}_tower(input); + assert_eq!(res, {expected.serialize(raw=True)}); +}} +""" + return code + + def write_all_tests(): random.seed(0) pairing_curve_ids = [CurveID.BN254, CurveID.BLS12_381] + + tower_pairing_test_header = """ +#[cfg(test)] +mod tower_pairing_tests { + use garaga::single_pairing_tower::{ + E12TOne, u384,G1Point, G2Point, E12T, miller_loop_bls12_381_tower, miller_loop_bn254_tower, final_exp_bls12_381_tower, final_exp_bn254_tower, expt_half_bls12_381_tower + }; + use garaga::ec_ops::{G1PointImpl}; + use garaga::ec_ops_g2::{G2PointImpl}; + use garaga::circuits::tower_circuits::{run_BN254_E12T_MUL_circuit, run_BLS12_381_E12T_MUL_circuit}; +""" + + with open(f"{TESTS_DIR}/tower_pairing_tests.cairo", "w") as f: + f.write(tower_pairing_test_header) + with concurrent.futures.ProcessPoolExecutor() as executor: + pairing_futures = [ + executor.submit(generate_tower_pairing_test, curve_id, n_pairs, 0) + for curve_id in pairing_curve_ids + for n_pairs in [1, 2, 3] + ] + final_exp_futures = [ + executor.submit(generate_tower_final_exp_test, curve_id, 0) + for curve_id in pairing_curve_ids + ] + expt_half_futures = [ + executor.submit(generate_expt_half_test, curve_id, 0) + for curve_id in [CurveID.BLS12_381] + ] + all_futures = pairing_futures + final_exp_futures + expt_half_futures + results = [future.result() for future in all_futures] + + for result in results: + f.write(result) + f.write("\n") + f.write("}") + subprocess.run(["scarb", "fmt"], check=True, cwd=f"{TESTS_DIR}") params = [(2, 2, False), (3, 2, True)] pairing_test_header = """ diff --git a/src/.tool-versions b/src/.tool-versions index cc60fd62..ff547533 100644 --- a/src/.tool-versions +++ b/src/.tool-versions @@ -1 +1 @@ -scarb 2.8.2 +scarb 2.8.4 diff --git a/src/Scarb.toml b/src/Scarb.toml index 3673e6a6..5212f7d3 100644 --- a/src/Scarb.toml +++ b/src/Scarb.toml @@ -15,7 +15,7 @@ sierra-replace-ids = false [dependencies] [dev-dependencies] -cairo_test = "2.8.2" +cairo_test = "2.8.4" #snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" } -#assert_macros = "2.8.2" +#assert_macros = "2.8." diff --git a/src/contracts/drand_quicknet/Scarb.toml b/src/contracts/drand_quicknet/Scarb.toml index 23acf04c..b21a3e15 100644 --- a/src/contracts/drand_quicknet/Scarb.toml +++ b/src/contracts/drand_quicknet/Scarb.toml @@ -5,7 +5,7 @@ edition = "2024_07" [dependencies] garaga = { path = "../.." } -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/src/contracts/drand_quicknet/src/drand_verifier.cairo b/src/contracts/drand_quicknet/src/drand_verifier.cairo index 181d9963..20322a38 100644 --- a/src/contracts/drand_quicknet/src/drand_verifier.cairo +++ b/src/contracts/drand_quicknet/src/drand_verifier.cairo @@ -12,7 +12,6 @@ mod DrandQuicknet { // use starknet::SyscallResultTrait; use garaga::definitions::{G1Point, G1G2Pair}; use garaga::pairing_check::{multi_pairing_check_bls12_381_2P_2F, MPCheckHintBLS12_381}; - // use garaga::ec_ops::{G1PointTrait, G2PointTrait}; use garaga::utils::drand::{ round_to_curve_bls12_381, DRAND_QUICKNET_PUBLIC_KEY, HashToCurveHint }; diff --git a/src/contracts/groth16_example_bls12_381/.tools-versions b/src/contracts/groth16_example_bls12_381/.tools-versions index cc60fd62..ff547533 100644 --- a/src/contracts/groth16_example_bls12_381/.tools-versions +++ b/src/contracts/groth16_example_bls12_381/.tools-versions @@ -1 +1 @@ -scarb 2.8.2 +scarb 2.8.4 diff --git a/src/contracts/groth16_example_bls12_381/Scarb.toml b/src/contracts/groth16_example_bls12_381/Scarb.toml index b0d20fd5..5fb50dc6 100644 --- a/src/contracts/groth16_example_bls12_381/Scarb.toml +++ b/src/contracts/groth16_example_bls12_381/Scarb.toml @@ -5,7 +5,7 @@ edition = "2024_07" [dependencies] garaga = { path = "../../" } -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/src/contracts/groth16_example_bls12_381/src/groth16_verifier.cairo b/src/contracts/groth16_example_bls12_381/src/groth16_verifier.cairo index 70bfe79c..a29d4421 100644 --- a/src/contracts/groth16_example_bls12_381/src/groth16_verifier.cairo +++ b/src/contracts/groth16_example_bls12_381/src/groth16_verifier.cairo @@ -12,12 +12,13 @@ mod Groth16VerifierBLS12_381 { use starknet::SyscallResultTrait; use garaga::definitions::{G1Point, G1G2Pair}; use garaga::groth16::{multi_pairing_check_bls12_381_3P_2F_with_extra_miller_loop_result}; - use garaga::ec_ops::{G1PointTrait, G2PointTrait, ec_safe_add}; + use garaga::ec_ops::{G1PointTrait, ec_safe_add}; + use garaga::ec_ops_g2::{G2PointTrait}; use garaga::utils::calldata::{deserialize_full_proof_with_hints_bls12_381}; use super::{N_PUBLIC_INPUTS, vk, ic, precomputed_lines}; const ECIP_OPS_CLASS_HASH: felt252 = - 0x2672f1f079ccbafe1be4a20a76421b509fcfb406cbf6818563ed812edaeb3a3; + 0x70c1d1c709c75e3cf51d79d19cf7c84a0d4521f3a2b8bf7bff5cb45ee0dd289; use starknet::ContractAddress; #[storage] diff --git a/src/contracts/groth16_example_bn254/.tools-versions b/src/contracts/groth16_example_bn254/.tools-versions index cc60fd62..ff547533 100644 --- a/src/contracts/groth16_example_bn254/.tools-versions +++ b/src/contracts/groth16_example_bn254/.tools-versions @@ -1 +1 @@ -scarb 2.8.2 +scarb 2.8.4 diff --git a/src/contracts/groth16_example_bn254/Scarb.toml b/src/contracts/groth16_example_bn254/Scarb.toml index 480c9a2e..01c5fb3b 100644 --- a/src/contracts/groth16_example_bn254/Scarb.toml +++ b/src/contracts/groth16_example_bn254/Scarb.toml @@ -5,7 +5,7 @@ edition = "2024_07" [dependencies] garaga = { path = "../../" } -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/src/contracts/groth16_example_bn254/src/groth16_verifier.cairo b/src/contracts/groth16_example_bn254/src/groth16_verifier.cairo index b1531d61..5f6aa276 100644 --- a/src/contracts/groth16_example_bn254/src/groth16_verifier.cairo +++ b/src/contracts/groth16_example_bn254/src/groth16_verifier.cairo @@ -12,12 +12,13 @@ mod Groth16VerifierBN254 { use starknet::SyscallResultTrait; use garaga::definitions::{G1Point, G1G2Pair}; use garaga::groth16::{multi_pairing_check_bn254_3P_2F_with_extra_miller_loop_result}; - use garaga::ec_ops::{G1PointTrait, G2PointTrait, ec_safe_add}; + use garaga::ec_ops::{G1PointTrait, ec_safe_add}; + use garaga::ec_ops_g2::{G2PointTrait}; use garaga::utils::calldata::{deserialize_full_proof_with_hints_bn254}; use super::{N_PUBLIC_INPUTS, vk, ic, precomputed_lines}; const ECIP_OPS_CLASS_HASH: felt252 = - 0x2672f1f079ccbafe1be4a20a76421b509fcfb406cbf6818563ed812edaeb3a3; + 0x70c1d1c709c75e3cf51d79d19cf7c84a0d4521f3a2b8bf7bff5cb45ee0dd289; use starknet::ContractAddress; #[storage] diff --git a/src/contracts/risc0_verifier_bn254/Scarb.toml b/src/contracts/risc0_verifier_bn254/Scarb.toml index 52a7df43..d61c4015 100644 --- a/src/contracts/risc0_verifier_bn254/Scarb.toml +++ b/src/contracts/risc0_verifier_bn254/Scarb.toml @@ -5,7 +5,7 @@ edition = "2024_07" [dependencies] garaga = { path = "../../" } -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/src/contracts/risc0_verifier_bn254/src/groth16_verifier.cairo b/src/contracts/risc0_verifier_bn254/src/groth16_verifier.cairo index 602f5b37..a96715f2 100644 --- a/src/contracts/risc0_verifier_bn254/src/groth16_verifier.cairo +++ b/src/contracts/risc0_verifier_bn254/src/groth16_verifier.cairo @@ -12,13 +12,14 @@ mod Risc0Groth16VerifierBN254 { use starknet::SyscallResultTrait; use garaga::definitions::{G1Point, G1G2Pair}; use garaga::groth16::{multi_pairing_check_bn254_3P_2F_with_extra_miller_loop_result}; - use garaga::ec_ops::{G1PointTrait, G2PointTrait, ec_safe_add}; + use garaga::ec_ops::{G1PointTrait, ec_safe_add}; + use garaga::ec_ops_g2::{G2PointTrait}; use garaga::utils::risc0::{compute_receipt_claim, journal_sha256}; use garaga::utils::calldata::deserialize_full_proof_with_hints_risc0; use super::{N_FREE_PUBLIC_INPUTS, vk, ic, precomputed_lines, T}; const ECIP_OPS_CLASS_HASH: felt252 = - 0x2672f1f079ccbafe1be4a20a76421b509fcfb406cbf6818563ed812edaeb3a3; + 0x70c1d1c709c75e3cf51d79d19cf7c84a0d4521f3a2b8bf7bff5cb45ee0dd289; #[storage] struct Storage {} diff --git a/src/contracts/universal_ecip/Scarb.toml b/src/contracts/universal_ecip/Scarb.toml index cf17c2d9..da691e45 100644 --- a/src/contracts/universal_ecip/Scarb.toml +++ b/src/contracts/universal_ecip/Scarb.toml @@ -5,7 +5,7 @@ edition = "2024_07" [dependencies] garaga = { path = "../.." } -starknet = "2.8.2" +starknet = "2.8.4" [cairo] sierra-replace-ids = false diff --git a/src/src/circuits.cairo b/src/src/circuits.cairo index c3f93370..9923f9dd 100644 --- a/src/src/circuits.cairo +++ b/src/src/circuits.cairo @@ -3,3 +3,4 @@ mod dummy; mod multi_pairing_check; mod extf_mul; mod isogeny; +mod tower_circuits; diff --git a/src/src/circuits/dummy.cairo b/src/src/circuits/dummy.cairo index 6deda304..aaaf11b1 100644 --- a/src/src/circuits/dummy.cairo +++ b/src/src/circuits/dummy.cairo @@ -14,6 +14,7 @@ use garaga::definitions::{ }; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; use core::option::Option; +use garaga::single_pairing_tower::E12T; #[inline(always)] fn run_DUMMY_circuit(mut input: Array, curve_index: usize) -> Array { diff --git a/src/src/circuits/ec.cairo b/src/src/circuits/ec.cairo index b7cdf0a9..fbdc2c1c 100644 --- a/src/src/circuits/ec.cairo +++ b/src/src/circuits/ec.cairo @@ -14,6 +14,7 @@ use garaga::definitions::{ }; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; use core::option::Option; +use garaga::single_pairing_tower::E12T; #[inline(always)] fn run_ACC_EVAL_POINT_CHALLENGE_SIGNED_circuit( @@ -169,6 +170,80 @@ fn run_ACC_FUNCTION_CHALLENGE_DUPL_circuit( return (next_f_a0_accs, next_f_a1_accs, next_xA0_power, next_xA2_power); } #[inline(always)] +fn run_ADD_EC_POINTS_G2_circuit(p: G2Point, q: G2Point, curve_index: usize) -> (G2Point,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + + // INPUT stack + let (in1, in2, in3) = (CE::> {}, CE::> {}, CE::> {}); + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let (in7, in8) = (CE::> {}, CE::> {}); + let t0 = circuit_sub(in3, in7); // Fp2 sub coeff 0/1 + let t1 = circuit_sub(in4, in8); // Fp2 sub coeff 1/1 + let t2 = circuit_sub(in1, in5); // Fp2 sub coeff 0/1 + let t3 = circuit_sub(in2, in6); // Fp2 sub coeff 1/1 + let t4 = circuit_mul(t2, t2); // Fp2 Inv start + let t5 = circuit_mul(t3, t3); + let t6 = circuit_add(t4, t5); + let t7 = circuit_inverse(t6); + let t8 = circuit_mul(t2, t7); // Fp2 Inv real part end + let t9 = circuit_mul(t3, t7); + let t10 = circuit_sub(in0, t9); // Fp2 Inv imag part end + let t11 = circuit_mul(t0, t8); // Fp2 mul start + let t12 = circuit_mul(t1, t10); + let t13 = circuit_sub(t11, t12); // Fp2 mul real part end + let t14 = circuit_mul(t0, t10); + let t15 = circuit_mul(t1, t8); + let t16 = circuit_add(t14, t15); // Fp2 mul imag part end + let t17 = circuit_add(t13, t16); + let t18 = circuit_sub(t13, t16); + let t19 = circuit_mul(t17, t18); + let t20 = circuit_mul(t13, t16); + let t21 = circuit_add(t20, t20); + let t22 = circuit_sub(t19, in1); // Fp2 sub coeff 0/1 + let t23 = circuit_sub(t21, in2); // Fp2 sub coeff 1/1 + let t24 = circuit_sub(t22, in5); // Fp2 sub coeff 0/1 + let t25 = circuit_sub(t23, in6); // Fp2 sub coeff 1/1 + let t26 = circuit_sub(in1, t24); // Fp2 sub coeff 0/1 + let t27 = circuit_sub(in2, t25); // Fp2 sub coeff 1/1 + let t28 = circuit_mul(t13, t26); // Fp2 mul start + let t29 = circuit_mul(t16, t27); + let t30 = circuit_sub(t28, t29); // Fp2 mul real part end + let t31 = circuit_mul(t13, t27); + let t32 = circuit_mul(t16, t26); + let t33 = circuit_add(t31, t32); // Fp2 mul imag part end + let t34 = circuit_sub(t30, in3); // Fp2 sub coeff 0/1 + let t35 = circuit_sub(t33, in4); // Fp2 sub coeff 1/1 + + let modulus = get_p(curve_index); + let modulus = TryInto::< + _, CircuitModulus + >::try_into([modulus.limb0, modulus.limb1, modulus.limb2, modulus.limb3]) + .unwrap(); + + let mut circuit_inputs = (t24, t25, t34, t35,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(p.x0); // in1 + circuit_inputs = circuit_inputs.next_2(p.x1); // in2 + circuit_inputs = circuit_inputs.next_2(p.y0); // in3 + circuit_inputs = circuit_inputs.next_2(p.y1); // in4 + circuit_inputs = circuit_inputs.next_2(q.x0); // in5 + circuit_inputs = circuit_inputs.next_2(q.x1); // in6 + circuit_inputs = circuit_inputs.next_2(q.y0); // in7 + circuit_inputs = circuit_inputs.next_2(q.y1); // in8 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let result: G2Point = G2Point { + x0: outputs.get_output(t24), + x1: outputs.get_output(t25), + y0: outputs.get_output(t34), + y1: outputs.get_output(t35) + }; + return (result,); +} +#[inline(always)] fn run_ADD_EC_POINT_circuit(p: G1Point, q: G1Point, curve_index: usize) -> (G1Point,) { // INPUT stack let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); @@ -204,6 +279,82 @@ fn run_ADD_EC_POINT_circuit(p: G1Point, q: G1Point, curve_index: usize) -> (G1Po return (r,); } #[inline(always)] +fn run_DOUBLE_EC_POINT_G2_A_EQ_0_circuit(p: G2Point, curve_index: usize) -> (G2Point,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x3 + let in1 = CE::> {}; // 0x0 + + // INPUT stack + let (in2, in3, in4) = (CE::> {}, CE::> {}, CE::> {}); + let in5 = CE::> {}; + let t0 = circuit_add(in2, in3); + let t1 = circuit_sub(in2, in3); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in2, in3); + let t4 = circuit_add(t3, t3); + let t5 = circuit_mul(t2, in0); // Fp2 scalar mul coeff 0/1 + let t6 = circuit_mul(t4, in0); // Fp2 scalar mul coeff 1/1 + let t7 = circuit_add(in4, in4); // Fp2 add coeff 0/1 + let t8 = circuit_add(in5, in5); // Fp2 add coeff 1/1 + let t9 = circuit_mul(t7, t7); // Fp2 Inv start + let t10 = circuit_mul(t8, t8); + let t11 = circuit_add(t9, t10); + let t12 = circuit_inverse(t11); + let t13 = circuit_mul(t7, t12); // Fp2 Inv real part end + let t14 = circuit_mul(t8, t12); + let t15 = circuit_sub(in1, t14); // Fp2 Inv imag part end + let t16 = circuit_mul(t5, t13); // Fp2 mul start + let t17 = circuit_mul(t6, t15); + let t18 = circuit_sub(t16, t17); // Fp2 mul real part end + let t19 = circuit_mul(t5, t15); + let t20 = circuit_mul(t6, t13); + let t21 = circuit_add(t19, t20); // Fp2 mul imag part end + let t22 = circuit_add(t18, t21); + let t23 = circuit_sub(t18, t21); + let t24 = circuit_mul(t22, t23); + let t25 = circuit_mul(t18, t21); + let t26 = circuit_add(t25, t25); + let t27 = circuit_sub(t24, in2); // Fp2 sub coeff 0/1 + let t28 = circuit_sub(t26, in3); // Fp2 sub coeff 1/1 + let t29 = circuit_sub(t27, in2); // Fp2 sub coeff 0/1 + let t30 = circuit_sub(t28, in3); // Fp2 sub coeff 1/1 + let t31 = circuit_sub(in2, t29); // Fp2 sub coeff 0/1 + let t32 = circuit_sub(in3, t30); // Fp2 sub coeff 1/1 + let t33 = circuit_mul(t18, t31); // Fp2 mul start + let t34 = circuit_mul(t21, t32); + let t35 = circuit_sub(t33, t34); // Fp2 mul real part end + let t36 = circuit_mul(t18, t32); + let t37 = circuit_mul(t21, t31); + let t38 = circuit_add(t36, t37); // Fp2 mul imag part end + let t39 = circuit_sub(t35, in4); // Fp2 sub coeff 0/1 + let t40 = circuit_sub(t38, in5); // Fp2 sub coeff 1/1 + + let modulus = get_p(curve_index); + let modulus = TryInto::< + _, CircuitModulus + >::try_into([modulus.limb0, modulus.limb1, modulus.limb2, modulus.limb3]) + .unwrap(); + + let mut circuit_inputs = (t29, t30, t39, t40,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x3, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in1 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(p.x0); // in2 + circuit_inputs = circuit_inputs.next_2(p.x1); // in3 + circuit_inputs = circuit_inputs.next_2(p.y0); // in4 + circuit_inputs = circuit_inputs.next_2(p.y1); // in5 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let result: G2Point = G2Point { + x0: outputs.get_output(t29), + x1: outputs.get_output(t30), + y0: outputs.get_output(t39), + y1: outputs.get_output(t40) + }; + return (result,); +} +#[inline(always)] fn run_DOUBLE_EC_POINT_circuit(p: G1Point, A_weirstrass: u384, curve_index: usize) -> (G1Point,) { // CONSTANT stack let in0 = CE::> {}; // 0x3 @@ -221,7 +372,7 @@ fn run_DOUBLE_EC_POINT_circuit(p: G1Point, A_weirstrass: u384, curve_index: usiz let t8 = circuit_sub(t7, in1); let t9 = circuit_sub(in1, t8); let t10 = circuit_mul(t5, t9); - let t11 = circuit_sub(in2, t10); + let t11 = circuit_sub(t10, in2); let modulus = get_p(curve_index); let modulus = TryInto::< @@ -2770,7 +2921,8 @@ mod tests { use super::{ run_ACC_EVAL_POINT_CHALLENGE_SIGNED_circuit, run_ACC_FUNCTION_CHALLENGE_DUPL_circuit, - run_ADD_EC_POINT_circuit, run_DOUBLE_EC_POINT_circuit, + run_ADD_EC_POINTS_G2_circuit, run_ADD_EC_POINT_circuit, + run_DOUBLE_EC_POINT_G2_A_EQ_0_circuit, run_DOUBLE_EC_POINT_circuit, run_EVAL_FN_CHALLENGE_DUPL_10P_circuit, run_EVAL_FN_CHALLENGE_DUPL_1P_circuit, run_EVAL_FN_CHALLENGE_DUPL_2P_circuit, run_EVAL_FN_CHALLENGE_DUPL_3P_circuit, run_EVAL_FN_CHALLENGE_DUPL_4P_circuit, run_EVAL_FN_CHALLENGE_DUPL_5P_circuit, diff --git a/src/src/circuits/extf_mul.cairo b/src/src/circuits/extf_mul.cairo index 68375592..a542278e 100644 --- a/src/src/circuits/extf_mul.cairo +++ b/src/src/circuits/extf_mul.cairo @@ -14,6 +14,7 @@ use garaga::definitions::{ }; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; use core::option::Option; +use garaga::single_pairing_tower::E12T; #[inline(always)] fn run_BLS12_381_EVAL_E12D_circuit(f: E12D, z: u384) -> (u384,) { diff --git a/src/src/circuits/isogeny.cairo b/src/src/circuits/isogeny.cairo index 8dfbd6a0..3ec4fec4 100644 --- a/src/src/circuits/isogeny.cairo +++ b/src/src/circuits/isogeny.cairo @@ -14,6 +14,7 @@ use garaga::definitions::{ }; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; use core::option::Option; +use garaga::single_pairing_tower::E12T; #[inline(always)] fn run_BLS12_381_APPLY_ISOGENY_BLS12_381_circuit(pt: G1Point) -> (G1Point,) { diff --git a/src/src/circuits/multi_pairing_check.cairo b/src/src/circuits/multi_pairing_check.cairo index c8015a5e..cd9ffe6f 100644 --- a/src/src/circuits/multi_pairing_check.cairo +++ b/src/src/circuits/multi_pairing_check.cairo @@ -14,6 +14,7 @@ use garaga::definitions::{ }; use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; use core::option::Option; +use garaga::single_pairing_tower::E12T; #[inline(always)] fn run_BLS12_381_MP_CHECK_BIT00_2P_2F_circuit( @@ -225,13 +226,13 @@ fn run_BLS12_381_MP_CHECK_BIT00_3P_2F_circuit( let t39 = circuit_mul(t37, in1); // Doubling slope numerator end let t40 = circuit_add(in27, in27); // Fp2 add coeff 0/1 let t41 = circuit_add(in28, in28); // Fp2 add coeff 1/1 - let t42 = circuit_mul(t40, t40); // Fp2 Div x/y start : Fp2 Inv y start + let t42 = circuit_mul(t40, t40); // Fp2 Inv start let t43 = circuit_mul(t41, t41); let t44 = circuit_add(t42, t43); let t45 = circuit_inverse(t44); - let t46 = circuit_mul(t40, t45); // Fp2 Inv y real part end + let t46 = circuit_mul(t40, t45); // Fp2 Inv real part end let t47 = circuit_mul(t41, t45); - let t48 = circuit_sub(in2, t47); // Fp2 Inv y imag part end + let t48 = circuit_sub(in2, t47); // Fp2 Inv imag part end let t49 = circuit_mul(t38, t46); // Fp2 mul start let t50 = circuit_mul(t39, t48); let t51 = circuit_sub(t49, t50); // Fp2 mul real part end @@ -318,13 +319,13 @@ fn run_BLS12_381_MP_CHECK_BIT00_3P_2F_circuit( let t130 = circuit_mul(t128, in1); // Doubling slope numerator end let t131 = circuit_add(t72, t72); // Fp2 add coeff 0/1 let t132 = circuit_add(t73, t73); // Fp2 add coeff 1/1 - let t133 = circuit_mul(t131, t131); // Fp2 Div x/y start : Fp2 Inv y start + let t133 = circuit_mul(t131, t131); // Fp2 Inv start let t134 = circuit_mul(t132, t132); let t135 = circuit_add(t133, t134); let t136 = circuit_inverse(t135); - let t137 = circuit_mul(t131, t136); // Fp2 Inv y real part end + let t137 = circuit_mul(t131, t136); // Fp2 Inv real part end let t138 = circuit_mul(t132, t136); - let t139 = circuit_sub(in2, t138); // Fp2 Inv y imag part end + let t139 = circuit_sub(in2, t138); // Fp2 Inv imag part end let t140 = circuit_mul(t129, t137); // Fp2 mul start let t141 = circuit_mul(t130, t139); let t142 = circuit_sub(t140, t141); // Fp2 mul real part end @@ -588,13 +589,13 @@ fn run_BLS12_381_MP_CHECK_BIT0_3P_2F_circuit( let t39 = circuit_mul(t37, in1); // Doubling slope numerator end let t40 = circuit_add(in19, in19); // Fp2 add coeff 0/1 let t41 = circuit_add(in20, in20); // Fp2 add coeff 1/1 - let t42 = circuit_mul(t40, t40); // Fp2 Div x/y start : Fp2 Inv y start + let t42 = circuit_mul(t40, t40); // Fp2 Inv start let t43 = circuit_mul(t41, t41); let t44 = circuit_add(t42, t43); let t45 = circuit_inverse(t44); - let t46 = circuit_mul(t40, t45); // Fp2 Inv y real part end + let t46 = circuit_mul(t40, t45); // Fp2 Inv real part end let t47 = circuit_mul(t41, t45); - let t48 = circuit_sub(in2, t47); // Fp2 Inv y imag part end + let t48 = circuit_sub(in2, t47); // Fp2 Inv imag part end let t49 = circuit_mul(t38, t46); // Fp2 mul start let t50 = circuit_mul(t39, t48); let t51 = circuit_sub(t49, t50); // Fp2 mul real part end @@ -924,13 +925,13 @@ fn run_BLS12_381_MP_CHECK_BIT1_3P_2F_circuit( let t63 = circuit_sub(in26, in30); // Fp2 sub coeff 1/1 let t64 = circuit_sub(in23, in27); // Fp2 sub coeff 0/1 let t65 = circuit_sub(in24, in28); // Fp2 sub coeff 1/1 - let t66 = circuit_mul(t64, t64); // Fp2 Div x/y start : Fp2 Inv y start + let t66 = circuit_mul(t64, t64); // Fp2 Inv start let t67 = circuit_mul(t65, t65); let t68 = circuit_add(t66, t67); let t69 = circuit_inverse(t68); - let t70 = circuit_mul(t64, t69); // Fp2 Inv y real part end + let t70 = circuit_mul(t64, t69); // Fp2 Inv real part end let t71 = circuit_mul(t65, t69); - let t72 = circuit_sub(in0, t71); // Fp2 Inv y imag part end + let t72 = circuit_sub(in0, t71); // Fp2 Inv imag part end let t73 = circuit_mul(t62, t70); // Fp2 mul start let t74 = circuit_mul(t63, t72); let t75 = circuit_sub(t73, t74); // Fp2 mul real part end @@ -958,13 +959,13 @@ fn run_BLS12_381_MP_CHECK_BIT1_3P_2F_circuit( let t97 = circuit_add(in26, in26); // Fp2 add coeff 1/1 let t98 = circuit_sub(t86, in23); // Fp2 sub coeff 0/1 let t99 = circuit_sub(t87, in24); // Fp2 sub coeff 1/1 - let t100 = circuit_mul(t98, t98); // Fp2 Div x/y start : Fp2 Inv y start + let t100 = circuit_mul(t98, t98); // Fp2 Inv start let t101 = circuit_mul(t99, t99); let t102 = circuit_add(t100, t101); let t103 = circuit_inverse(t102); - let t104 = circuit_mul(t98, t103); // Fp2 Inv y real part end + let t104 = circuit_mul(t98, t103); // Fp2 Inv real part end let t105 = circuit_mul(t99, t103); - let t106 = circuit_sub(in0, t105); // Fp2 Inv y imag part end + let t106 = circuit_sub(in0, t105); // Fp2 Inv imag part end let t107 = circuit_mul(t96, t104); // Fp2 mul start let t108 = circuit_mul(t97, t106); let t109 = circuit_sub(t107, t108); // Fp2 mul real part end @@ -1969,13 +1970,13 @@ fn run_BLS12_381_MP_CHECK_INIT_BIT_3P_2F_circuit( let t67 = circuit_mul(t65, in1); let t68 = circuit_add(in27, in27); // Fp2 add coeff 0/1 let t69 = circuit_add(in28, in28); // Fp2 add coeff 1/1 - let t70 = circuit_mul(t68, t68); // Fp2 Div x/y start : Fp2 Inv y start + let t70 = circuit_mul(t68, t68); // Fp2 Inv start let t71 = circuit_mul(t69, t69); let t72 = circuit_add(t70, t71); let t73 = circuit_inverse(t72); - let t74 = circuit_mul(t68, t73); // Fp2 Inv y real part end + let t74 = circuit_mul(t68, t73); // Fp2 Inv real part end let t75 = circuit_mul(t69, t73); - let t76 = circuit_sub(in2, t75); // Fp2 Inv y imag part end + let t76 = circuit_sub(in2, t75); // Fp2 Inv imag part end let t77 = circuit_mul(t66, t74); // Fp2 mul start let t78 = circuit_mul(t67, t76); let t79 = circuit_sub(t77, t78); // Fp2 mul real part end @@ -2001,13 +2002,13 @@ fn run_BLS12_381_MP_CHECK_INIT_BIT_3P_2F_circuit( let t99 = circuit_sub(t95, t97); // Fp2 sub coeff 1/1 let t100 = circuit_sub(in25, t98); // Fp2 sub coeff 0/1 let t101 = circuit_sub(in26, t99); // Fp2 sub coeff 1/1 - let t102 = circuit_mul(t100, t100); // Fp2 Div x/y start : Fp2 Inv y start + let t102 = circuit_mul(t100, t100); // Fp2 Inv start let t103 = circuit_mul(t101, t101); let t104 = circuit_add(t102, t103); let t105 = circuit_inverse(t104); - let t106 = circuit_mul(t100, t105); // Fp2 Inv y real part end + let t106 = circuit_mul(t100, t105); // Fp2 Inv real part end let t107 = circuit_mul(t101, t105); - let t108 = circuit_sub(in2, t107); // Fp2 Inv y imag part end + let t108 = circuit_sub(in2, t107); // Fp2 Inv imag part end let t109 = circuit_mul(t68, t106); // Fp2 mul start let t110 = circuit_mul(t69, t108); let t111 = circuit_sub(t109, t110); // Fp2 mul real part end @@ -2748,13 +2749,13 @@ fn run_BN254_MP_CHECK_BIT00_3P_2F_circuit( let t46 = circuit_mul(t44, in3); // Doubling slope numerator end let t47 = circuit_add(in29, in29); // Fp2 add coeff 0/1 let t48 = circuit_add(in30, in30); // Fp2 add coeff 1/1 - let t49 = circuit_mul(t47, t47); // Fp2 Div x/y start : Fp2 Inv y start + let t49 = circuit_mul(t47, t47); // Fp2 Inv start let t50 = circuit_mul(t48, t48); let t51 = circuit_add(t49, t50); let t52 = circuit_inverse(t51); - let t53 = circuit_mul(t47, t52); // Fp2 Inv y real part end + let t53 = circuit_mul(t47, t52); // Fp2 Inv real part end let t54 = circuit_mul(t48, t52); - let t55 = circuit_sub(in4, t54); // Fp2 Inv y imag part end + let t55 = circuit_sub(in4, t54); // Fp2 Inv imag part end let t56 = circuit_mul(t45, t53); // Fp2 mul start let t57 = circuit_mul(t46, t55); let t58 = circuit_sub(t56, t57); // Fp2 mul real part end @@ -2850,13 +2851,13 @@ fn run_BN254_MP_CHECK_BIT00_3P_2F_circuit( let t146 = circuit_mul(t144, in3); // Doubling slope numerator end let t147 = circuit_add(t79, t79); // Fp2 add coeff 0/1 let t148 = circuit_add(t80, t80); // Fp2 add coeff 1/1 - let t149 = circuit_mul(t147, t147); // Fp2 Div x/y start : Fp2 Inv y start + let t149 = circuit_mul(t147, t147); // Fp2 Inv start let t150 = circuit_mul(t148, t148); let t151 = circuit_add(t149, t150); let t152 = circuit_inverse(t151); - let t153 = circuit_mul(t147, t152); // Fp2 Inv y real part end + let t153 = circuit_mul(t147, t152); // Fp2 Inv real part end let t154 = circuit_mul(t148, t152); - let t155 = circuit_sub(in4, t154); // Fp2 Inv y imag part end + let t155 = circuit_sub(in4, t154); // Fp2 Inv imag part end let t156 = circuit_mul(t145, t153); // Fp2 mul start let t157 = circuit_mul(t146, t155); let t158 = circuit_sub(t156, t157); // Fp2 mul real part end @@ -3152,13 +3153,13 @@ fn run_BN254_MP_CHECK_BIT0_3P_2F_circuit( let t46 = circuit_mul(t44, in3); // Doubling slope numerator end let t47 = circuit_add(in21, in21); // Fp2 add coeff 0/1 let t48 = circuit_add(in22, in22); // Fp2 add coeff 1/1 - let t49 = circuit_mul(t47, t47); // Fp2 Div x/y start : Fp2 Inv y start + let t49 = circuit_mul(t47, t47); // Fp2 Inv start let t50 = circuit_mul(t48, t48); let t51 = circuit_add(t49, t50); let t52 = circuit_inverse(t51); - let t53 = circuit_mul(t47, t52); // Fp2 Inv y real part end + let t53 = circuit_mul(t47, t52); // Fp2 Inv real part end let t54 = circuit_mul(t48, t52); - let t55 = circuit_sub(in4, t54); // Fp2 Inv y imag part end + let t55 = circuit_sub(in4, t54); // Fp2 Inv imag part end let t56 = circuit_mul(t45, t53); // Fp2 mul start let t57 = circuit_mul(t46, t55); let t58 = circuit_sub(t56, t57); // Fp2 mul real part end @@ -3532,13 +3533,13 @@ fn run_BN254_MP_CHECK_BIT1_3P_2F_circuit( let t76 = circuit_sub(in28, in32); // Fp2 sub coeff 1/1 let t77 = circuit_sub(in25, in29); // Fp2 sub coeff 0/1 let t78 = circuit_sub(in26, in30); // Fp2 sub coeff 1/1 - let t79 = circuit_mul(t77, t77); // Fp2 Div x/y start : Fp2 Inv y start + let t79 = circuit_mul(t77, t77); // Fp2 Inv start let t80 = circuit_mul(t78, t78); let t81 = circuit_add(t79, t80); let t82 = circuit_inverse(t81); - let t83 = circuit_mul(t77, t82); // Fp2 Inv y real part end + let t83 = circuit_mul(t77, t82); // Fp2 Inv real part end let t84 = circuit_mul(t78, t82); - let t85 = circuit_sub(in2, t84); // Fp2 Inv y imag part end + let t85 = circuit_sub(in2, t84); // Fp2 Inv imag part end let t86 = circuit_mul(t75, t83); // Fp2 mul start let t87 = circuit_mul(t76, t85); let t88 = circuit_sub(t86, t87); // Fp2 mul real part end @@ -3566,13 +3567,13 @@ fn run_BN254_MP_CHECK_BIT1_3P_2F_circuit( let t110 = circuit_add(in28, in28); // Fp2 add coeff 1/1 let t111 = circuit_sub(t99, in25); // Fp2 sub coeff 0/1 let t112 = circuit_sub(t100, in26); // Fp2 sub coeff 1/1 - let t113 = circuit_mul(t111, t111); // Fp2 Div x/y start : Fp2 Inv y start + let t113 = circuit_mul(t111, t111); // Fp2 Inv start let t114 = circuit_mul(t112, t112); let t115 = circuit_add(t113, t114); let t116 = circuit_inverse(t115); - let t117 = circuit_mul(t111, t116); // Fp2 Inv y real part end + let t117 = circuit_mul(t111, t116); // Fp2 Inv real part end let t118 = circuit_mul(t112, t116); - let t119 = circuit_sub(in2, t118); // Fp2 Inv y imag part end + let t119 = circuit_sub(in2, t118); // Fp2 Inv imag part end let t120 = circuit_mul(t109, t117); // Fp2 mul start let t121 = circuit_mul(t110, t119); let t122 = circuit_sub(t120, t121); // Fp2 mul real part end @@ -4352,13 +4353,13 @@ fn run_BN254_MP_CHECK_FINALIZE_BN_3P_2F_circuit( let t76 = circuit_sub(in39, t70); // Fp2 sub coeff 1/1 let t77 = circuit_sub(in36, t61); // Fp2 sub coeff 0/1 let t78 = circuit_sub(in37, t64); // Fp2 sub coeff 1/1 - let t79 = circuit_mul(t77, t77); // Fp2 Div x/y start : Fp2 Inv y start + let t79 = circuit_mul(t77, t77); // Fp2 Inv start let t80 = circuit_mul(t78, t78); let t81 = circuit_add(t79, t80); let t82 = circuit_inverse(t81); - let t83 = circuit_mul(t77, t82); // Fp2 Inv y real part end + let t83 = circuit_mul(t77, t82); // Fp2 Inv real part end let t84 = circuit_mul(t78, t82); - let t85 = circuit_sub(in6, t84); // Fp2 Inv y imag part end + let t85 = circuit_sub(in6, t84); // Fp2 Inv imag part end let t86 = circuit_mul(t75, t83); // Fp2 mul start let t87 = circuit_mul(t76, t85); let t88 = circuit_sub(t86, t87); // Fp2 mul real part end @@ -4396,13 +4397,13 @@ fn run_BN254_MP_CHECK_FINALIZE_BN_3P_2F_circuit( let t120 = circuit_sub(t110, t74); // Fp2 sub coeff 1/1 let t121 = circuit_sub(t99, t71); // Fp2 sub coeff 0/1 let t122 = circuit_sub(t100, t72); // Fp2 sub coeff 1/1 - let t123 = circuit_mul(t121, t121); // Fp2 Div x/y start : Fp2 Inv y start + let t123 = circuit_mul(t121, t121); // Fp2 Inv start let t124 = circuit_mul(t122, t122); let t125 = circuit_add(t123, t124); let t126 = circuit_inverse(t125); - let t127 = circuit_mul(t121, t126); // Fp2 Inv y real part end + let t127 = circuit_mul(t121, t126); // Fp2 Inv real part end let t128 = circuit_mul(t122, t126); - let t129 = circuit_sub(in6, t128); // Fp2 Inv y imag part end + let t129 = circuit_sub(in6, t128); // Fp2 Inv imag part end let t130 = circuit_mul(t119, t127); // Fp2 mul start let t131 = circuit_mul(t120, t129); let t132 = circuit_sub(t130, t131); // Fp2 mul real part end @@ -5077,13 +5078,13 @@ fn run_BN254_MP_CHECK_INIT_BIT_3P_2F_circuit( let t46 = circuit_mul(t44, in3); // Doubling slope numerator end let t47 = circuit_add(in21, in21); // Fp2 add coeff 0/1 let t48 = circuit_add(in22, in22); // Fp2 add coeff 1/1 - let t49 = circuit_mul(t47, t47); // Fp2 Div x/y start : Fp2 Inv y start + let t49 = circuit_mul(t47, t47); // Fp2 Inv start let t50 = circuit_mul(t48, t48); let t51 = circuit_add(t49, t50); let t52 = circuit_inverse(t51); - let t53 = circuit_mul(t47, t52); // Fp2 Inv y real part end + let t53 = circuit_mul(t47, t52); // Fp2 Inv real part end let t54 = circuit_mul(t48, t52); - let t55 = circuit_sub(in4, t54); // Fp2 Inv y imag part end + let t55 = circuit_sub(in4, t54); // Fp2 Inv imag part end let t56 = circuit_mul(t45, t53); // Fp2 mul start let t57 = circuit_mul(t46, t55); let t58 = circuit_sub(t56, t57); // Fp2 mul real part end diff --git a/src/src/circuits/tower_circuits.cairo b/src/src/circuits/tower_circuits.cairo new file mode 100644 index 00000000..84de9bee --- /dev/null +++ b/src/src/circuits/tower_circuits.cairo @@ -0,0 +1,6189 @@ +use core::circuit::{ + RangeCheck96, AddMod, MulMod, u384, u96, CircuitElement, CircuitInput, circuit_add, circuit_sub, + circuit_mul, circuit_inverse, EvalCircuitResult, EvalCircuitTrait, CircuitOutputsTrait, + CircuitModulus, AddInputResultTrait, CircuitInputs, CircuitDefinition, CircuitData, + CircuitInputAccumulator +}; +use garaga::core::circuit::AddInputResultTrait2; +use core::circuit::CircuitElement as CE; +use core::circuit::CircuitInput as CI; +use garaga::definitions::{ + get_a, get_b, get_p, get_g, get_min_one, G1Point, G2Point, E12D, u288, E12DMulQuotient, + G1G2Pair, BNProcessedPair, BLSProcessedPair, MillerLoopResultScalingFactor, G2Line, + get_BLS12_381_modulus, get_BN254_modulus +}; +use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; +use core::option::Option; +use garaga::single_pairing_tower::E12T; + + +impl CircuitDefinition16< + E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15 +> of core::circuit::CircuitDefinition< + ( + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE + ) +> { + type CircuitType = + core::circuit::Circuit< + (E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15,) + >; +} +impl MyDrp_16< + E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15 +> of Drop< + ( + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE, + CE + ) +>; +#[inline(always)] +fn run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(M: E12T) -> (E12T,) { + // INPUT stack + let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); + let (in3, in4, in5) = (CE::> {}, CE::> {}, CE::> {}); + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in8, in9); + let t1 = circuit_sub(in8, in9); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in8, in9); + let t4 = circuit_add(t3, t3); + let t5 = circuit_add(in0, in1); + let t6 = circuit_sub(in0, in1); + let t7 = circuit_mul(t5, t6); + let t8 = circuit_mul(in0, in1); + let t9 = circuit_add(t8, t8); + let t10 = circuit_add(in8, in0); // Fp2 add coeff 0/1 + let t11 = circuit_add(in9, in1); // Fp2 add coeff 1/1 + let t12 = circuit_add(t10, t11); + let t13 = circuit_sub(t10, t11); + let t14 = circuit_mul(t12, t13); + let t15 = circuit_mul(t10, t11); + let t16 = circuit_add(t15, t15); + let t17 = circuit_sub(t14, t2); // Fp2 sub coeff 0/1 + let t18 = circuit_sub(t16, t4); // Fp2 sub coeff 1/1 + let t19 = circuit_sub(t17, t7); // Fp2 sub coeff 0/1 + let t20 = circuit_sub(t18, t9); // Fp2 sub coeff 1/1 + let t21 = circuit_add(in4, in5); + let t22 = circuit_sub(in4, in5); + let t23 = circuit_mul(t21, t22); + let t24 = circuit_mul(in4, in5); + let t25 = circuit_add(t24, t24); + let t26 = circuit_add(in6, in7); + let t27 = circuit_sub(in6, in7); + let t28 = circuit_mul(t26, t27); + let t29 = circuit_mul(in6, in7); + let t30 = circuit_add(t29, t29); + let t31 = circuit_add(in4, in6); // Fp2 add coeff 0/1 + let t32 = circuit_add(in5, in7); // Fp2 add coeff 1/1 + let t33 = circuit_add(t31, t32); + let t34 = circuit_sub(t31, t32); + let t35 = circuit_mul(t33, t34); + let t36 = circuit_mul(t31, t32); + let t37 = circuit_add(t36, t36); + let t38 = circuit_sub(t35, t23); // Fp2 sub coeff 0/1 + let t39 = circuit_sub(t37, t25); // Fp2 sub coeff 1/1 + let t40 = circuit_sub(t38, t28); // Fp2 sub coeff 0/1 + let t41 = circuit_sub(t39, t30); // Fp2 sub coeff 1/1 + let t42 = circuit_add(in10, in11); + let t43 = circuit_sub(in10, in11); + let t44 = circuit_mul(t42, t43); + let t45 = circuit_mul(in10, in11); + let t46 = circuit_add(t45, t45); + let t47 = circuit_add(in2, in3); + let t48 = circuit_sub(in2, in3); + let t49 = circuit_mul(t47, t48); + let t50 = circuit_mul(in2, in3); + let t51 = circuit_add(t50, t50); + let t52 = circuit_add(in10, in2); // Fp2 add coeff 0/1 + let t53 = circuit_add(in11, in3); // Fp2 add coeff 1/1 + let t54 = circuit_add(t52, t53); + let t55 = circuit_sub(t52, t53); + let t56 = circuit_mul(t54, t55); + let t57 = circuit_mul(t52, t53); + let t58 = circuit_add(t57, t57); + let t59 = circuit_sub(t56, t44); // Fp2 sub coeff 0/1 + let t60 = circuit_sub(t58, t46); // Fp2 sub coeff 1/1 + let t61 = circuit_sub(t59, t49); // Fp2 sub coeff 0/1 + let t62 = circuit_sub(t60, t51); // Fp2 sub coeff 1/1 + let t63 = circuit_add(t61, t62); + let t64 = circuit_add(t63, t63); + let t65 = circuit_sub(t61, t62); + let t66 = circuit_sub(t64, t61); + let t67 = circuit_sub(t66, t62); + let t68 = circuit_add(t2, t4); + let t69 = circuit_add(t68, t68); + let t70 = circuit_sub(t2, t4); + let t71 = circuit_sub(t69, t2); + let t72 = circuit_sub(t71, t4); + let t73 = circuit_add(t70, t7); // Fp2 add coeff 0/1 + let t74 = circuit_add(t72, t9); // Fp2 add coeff 1/1 + let t75 = circuit_add(t23, t25); + let t76 = circuit_add(t75, t75); + let t77 = circuit_sub(t23, t25); + let t78 = circuit_sub(t76, t23); + let t79 = circuit_sub(t78, t25); + let t80 = circuit_add(t77, t28); // Fp2 add coeff 0/1 + let t81 = circuit_add(t79, t30); // Fp2 add coeff 1/1 + let t82 = circuit_add(t44, t46); + let t83 = circuit_add(t82, t82); + let t84 = circuit_sub(t44, t46); + let t85 = circuit_sub(t83, t44); + let t86 = circuit_sub(t85, t46); + let t87 = circuit_add(t84, t49); // Fp2 add coeff 0/1 + let t88 = circuit_add(t86, t51); // Fp2 add coeff 1/1 + let t89 = circuit_sub(t73, in0); // Fp2 sub coeff 0/1 + let t90 = circuit_sub(t74, in1); // Fp2 sub coeff 1/1 + let t91 = circuit_add(t89, t89); // Fp2 add coeff 0/1 + let t92 = circuit_add(t90, t90); // Fp2 add coeff 1/1 + let t93 = circuit_add(t91, t73); // Fp2 add coeff 0/1 + let t94 = circuit_add(t92, t74); // Fp2 add coeff 1/1 + let t95 = circuit_sub(t80, in2); // Fp2 sub coeff 0/1 + let t96 = circuit_sub(t81, in3); // Fp2 sub coeff 1/1 + let t97 = circuit_add(t95, t95); // Fp2 add coeff 0/1 + let t98 = circuit_add(t96, t96); // Fp2 add coeff 1/1 + let t99 = circuit_add(t97, t80); // Fp2 add coeff 0/1 + let t100 = circuit_add(t98, t81); // Fp2 add coeff 1/1 + let t101 = circuit_sub(t87, in4); // Fp2 sub coeff 0/1 + let t102 = circuit_sub(t88, in5); // Fp2 sub coeff 1/1 + let t103 = circuit_add(t101, t101); // Fp2 add coeff 0/1 + let t104 = circuit_add(t102, t102); // Fp2 add coeff 1/1 + let t105 = circuit_add(t103, t87); // Fp2 add coeff 0/1 + let t106 = circuit_add(t104, t88); // Fp2 add coeff 1/1 + let t107 = circuit_add(t65, in6); // Fp2 add coeff 0/1 + let t108 = circuit_add(t67, in7); // Fp2 add coeff 1/1 + let t109 = circuit_add(t107, t107); // Fp2 add coeff 0/1 + let t110 = circuit_add(t108, t108); // Fp2 add coeff 1/1 + let t111 = circuit_add(t109, t65); // Fp2 add coeff 0/1 + let t112 = circuit_add(t110, t67); // Fp2 add coeff 1/1 + let t113 = circuit_add(t19, in8); // Fp2 add coeff 0/1 + let t114 = circuit_add(t20, in9); // Fp2 add coeff 1/1 + let t115 = circuit_add(t113, t113); // Fp2 add coeff 0/1 + let t116 = circuit_add(t114, t114); // Fp2 add coeff 1/1 + let t117 = circuit_add(t115, t19); // Fp2 add coeff 0/1 + let t118 = circuit_add(t116, t20); // Fp2 add coeff 1/1 + let t119 = circuit_add(t40, in10); // Fp2 add coeff 0/1 + let t120 = circuit_add(t41, in11); // Fp2 add coeff 1/1 + let t121 = circuit_add(t119, t119); // Fp2 add coeff 0/1 + let t122 = circuit_add(t120, t120); // Fp2 add coeff 1/1 + let t123 = circuit_add(t121, t40); // Fp2 add coeff 0/1 + let t124 = circuit_add(t122, t41); // Fp2 add coeff 1/1 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t93, t94, t99, t100, t105, t106, t111, t112, t117, t118, t123, t124,) + .new_inputs(); + // Prefill constants: + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in0 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in1 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in2 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in3 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in4 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in5 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in6 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in7 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in8 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in9 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in10 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in11 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t93), + c0b0a1: outputs.get_output(t94), + c0b1a0: outputs.get_output(t99), + c0b1a1: outputs.get_output(t100), + c0b2a0: outputs.get_output(t105), + c0b2a1: outputs.get_output(t106), + c1b0a0: outputs.get_output(t111), + c1b0a1: outputs.get_output(t112), + c1b1a0: outputs.get_output(t117), + c1b1a1: outputs.get_output(t118), + c1b2a0: outputs.get_output(t123), + c1b2a1: outputs.get_output(t124), + }; + return (res,); +} +#[inline(always)] +fn run_BLS12_381_E12T_CYCLO_SQUARE_COMPRESSED_circuit( + xc0b1a0: u384, + xc0b1a1: u384, + xc0b2a0: u384, + xc0b2a1: u384, + xc1b0a0: u384, + xc1b0a1: u384, + xc1b2a0: u384, + xc1b2a1: u384 +) -> (u384, u384, u384, u384, u384, u384, u384, u384) { + // INPUT stack + let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); + let (in3, in4, in5) = (CE::> {}, CE::> {}, CE::> {}); + let (in6, in7) = (CE::> {}, CE::> {}); + let t0 = circuit_add(in0, in1); + let t1 = circuit_sub(in0, in1); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in0, in1); + let t4 = circuit_add(t3, t3); + let t5 = circuit_add(in6, in7); + let t6 = circuit_sub(in6, in7); + let t7 = circuit_mul(t5, t6); + let t8 = circuit_mul(in6, in7); + let t9 = circuit_add(t8, t8); + let t10 = circuit_add(in0, in6); // Fp2 add coeff 0/1 + let t11 = circuit_add(in1, in7); // Fp2 add coeff 1/1 + let t12 = circuit_add(t10, t11); + let t13 = circuit_sub(t10, t11); + let t14 = circuit_mul(t12, t13); + let t15 = circuit_mul(t10, t11); + let t16 = circuit_add(t15, t15); + let t17 = circuit_add(t2, t7); // Fp2 add coeff 0/1 + let t18 = circuit_add(t4, t9); // Fp2 add coeff 1/1 + let t19 = circuit_sub(t14, t17); // Fp2 sub coeff 0/1 + let t20 = circuit_sub(t16, t18); // Fp2 sub coeff 1/1 + let t21 = circuit_add(in4, in2); // Fp2 add coeff 0/1 + let t22 = circuit_add(in5, in3); // Fp2 add coeff 1/1 + let t23 = circuit_add(t21, t22); + let t24 = circuit_sub(t21, t22); + let t25 = circuit_mul(t23, t24); + let t26 = circuit_mul(t21, t22); + let t27 = circuit_add(t26, t26); + let t28 = circuit_add(in4, in5); + let t29 = circuit_sub(in4, in5); + let t30 = circuit_mul(t28, t29); + let t31 = circuit_mul(in4, in5); + let t32 = circuit_add(t31, t31); + let t33 = circuit_add(t19, t20); + let t34 = circuit_add(t33, t33); + let t35 = circuit_sub(t19, t20); + let t36 = circuit_sub(t34, t19); + let t37 = circuit_sub(t36, t20); + let t38 = circuit_add(t35, in4); // Fp2 add coeff 0/1 + let t39 = circuit_add(t37, in5); // Fp2 add coeff 1/1 + let t40 = circuit_add(t38, t38); // Fp2 add coeff 0/1 + let t41 = circuit_add(t39, t39); // Fp2 add coeff 1/1 + let t42 = circuit_add(t40, t35); // Fp2 add coeff 0/1 + let t43 = circuit_add(t41, t37); // Fp2 add coeff 1/1 + let t44 = circuit_add(t7, t9); + let t45 = circuit_add(t44, t44); + let t46 = circuit_sub(t7, t9); + let t47 = circuit_sub(t45, t7); + let t48 = circuit_sub(t47, t9); + let t49 = circuit_add(t2, t46); // Fp2 add coeff 0/1 + let t50 = circuit_add(t4, t48); // Fp2 add coeff 1/1 + let t51 = circuit_sub(t49, in2); // Fp2 sub coeff 0/1 + let t52 = circuit_sub(t50, in3); // Fp2 sub coeff 1/1 + let t53 = circuit_add(in2, in3); + let t54 = circuit_sub(in2, in3); + let t55 = circuit_mul(t53, t54); + let t56 = circuit_mul(in2, in3); + let t57 = circuit_add(t56, t56); + let t58 = circuit_add(t51, t51); // Fp2 add coeff 0/1 + let t59 = circuit_add(t52, t52); // Fp2 add coeff 1/1 + let t60 = circuit_add(t58, t49); // Fp2 add coeff 0/1 + let t61 = circuit_add(t59, t50); // Fp2 add coeff 1/1 + let t62 = circuit_add(t55, t57); + let t63 = circuit_add(t62, t62); + let t64 = circuit_sub(t55, t57); + let t65 = circuit_sub(t63, t55); + let t66 = circuit_sub(t65, t57); + let t67 = circuit_add(t30, t64); // Fp2 add coeff 0/1 + let t68 = circuit_add(t32, t66); // Fp2 add coeff 1/1 + let t69 = circuit_sub(t67, in0); // Fp2 sub coeff 0/1 + let t70 = circuit_sub(t68, in1); // Fp2 sub coeff 1/1 + let t71 = circuit_add(t69, t69); // Fp2 add coeff 0/1 + let t72 = circuit_add(t70, t70); // Fp2 add coeff 1/1 + let t73 = circuit_add(t71, t67); // Fp2 add coeff 0/1 + let t74 = circuit_add(t72, t68); // Fp2 add coeff 1/1 + let t75 = circuit_add(t30, t55); // Fp2 add coeff 0/1 + let t76 = circuit_add(t32, t57); // Fp2 add coeff 1/1 + let t77 = circuit_sub(t25, t75); // Fp2 sub coeff 0/1 + let t78 = circuit_sub(t27, t76); // Fp2 sub coeff 1/1 + let t79 = circuit_add(t77, in6); // Fp2 add coeff 0/1 + let t80 = circuit_add(t78, in7); // Fp2 add coeff 1/1 + let t81 = circuit_add(t79, t79); // Fp2 add coeff 0/1 + let t82 = circuit_add(t80, t80); // Fp2 add coeff 1/1 + let t83 = circuit_add(t77, t81); // Fp2 add coeff 0/1 + let t84 = circuit_add(t78, t82); // Fp2 add coeff 1/1 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t73, t74, t60, t61, t42, t43, t83, t84,).new_inputs(); + // Prefill constants: + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(xc0b1a0); // in0 + circuit_inputs = circuit_inputs.next_2(xc0b1a1); // in1 + circuit_inputs = circuit_inputs.next_2(xc0b2a0); // in2 + circuit_inputs = circuit_inputs.next_2(xc0b2a1); // in3 + circuit_inputs = circuit_inputs.next_2(xc1b0a0); // in4 + circuit_inputs = circuit_inputs.next_2(xc1b0a1); // in5 + circuit_inputs = circuit_inputs.next_2(xc1b2a0); // in6 + circuit_inputs = circuit_inputs.next_2(xc1b2a1); // in7 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let xc0b1a0: u384 = outputs.get_output(t73); + let xc0b1a1: u384 = outputs.get_output(t74); + let xc0b2a0: u384 = outputs.get_output(t60); + let xc0b2a1: u384 = outputs.get_output(t61); + let xc1b0a0: u384 = outputs.get_output(t42); + let xc1b0a1: u384 = outputs.get_output(t43); + let xc1b2a0: u384 = outputs.get_output(t83); + let xc1b2a1: u384 = outputs.get_output(t84); + return (xc0b1a0, xc0b1a1, xc0b2a0, xc0b2a1, xc1b0a0, xc1b0a1, xc1b2a0, xc1b2a1); +} +#[inline(always)] +fn run_BLS12_381_E12T_DECOMP_KARABINA_II_circuit( + t0a0: u384, + t0a1: u384, + t1a0: u384, + t1a1: u384, + xc0b1a0: u384, + xc0b1a1: u384, + xc0b2a0: u384, + xc0b2a1: u384, + xc1b0a0: u384, + xc1b0a1: u384, + xc1b2a0: u384, + xc1b2a1: u384 +) -> (u384, u384, u384, u384) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x1 + + // INPUT stack + let (in2, in3, in4) = (CE::> {}, CE::> {}, CE::> {}); + let (in5, in6, in7) = (CE::> {}, CE::> {}, CE::> {}); + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_mul(in4, in4); // Fp2 Inv start + let t1 = circuit_mul(in5, in5); + let t2 = circuit_add(t0, t1); + let t3 = circuit_inverse(t2); + let t4 = circuit_mul(in4, t3); // Fp2 Inv real part end + let t5 = circuit_mul(in5, t3); + let t6 = circuit_sub(in0, t5); // Fp2 Inv imag part end + let t7 = circuit_mul(in2, t4); // Fp2 mul start + let t8 = circuit_mul(in3, t6); + let t9 = circuit_sub(t7, t8); // Fp2 mul real part end + let t10 = circuit_mul(in2, t6); + let t11 = circuit_mul(in3, t4); + let t12 = circuit_add(t10, t11); // Fp2 mul imag part end + let t13 = circuit_mul(in8, in6); // Fp2 mul start + let t14 = circuit_mul(in9, in7); + let t15 = circuit_sub(t13, t14); // Fp2 mul real part end + let t16 = circuit_mul(in8, in7); + let t17 = circuit_mul(in9, in6); + let t18 = circuit_add(t16, t17); // Fp2 mul imag part end + let t19 = circuit_add(t9, t12); + let t20 = circuit_sub(t9, t12); + let t21 = circuit_mul(t19, t20); + let t22 = circuit_mul(t9, t12); + let t23 = circuit_add(t22, t22); + let t24 = circuit_sub(t21, t15); // Fp2 sub coeff 0/1 + let t25 = circuit_sub(t23, t18); // Fp2 sub coeff 1/1 + let t26 = circuit_add(t24, t24); // Fp2 add coeff 0/1 + let t27 = circuit_add(t25, t25); // Fp2 add coeff 1/1 + let t28 = circuit_sub(t26, t15); // Fp2 sub coeff 0/1 + let t29 = circuit_sub(t27, t18); // Fp2 sub coeff 1/1 + let t30 = circuit_mul(in10, in12); // Fp2 mul start + let t31 = circuit_mul(in11, in13); + let t32 = circuit_sub(t30, t31); // Fp2 mul real part end + let t33 = circuit_mul(in10, in13); + let t34 = circuit_mul(in11, in12); + let t35 = circuit_add(t33, t34); // Fp2 mul imag part end + let t36 = circuit_add(t28, t32); // Fp2 add coeff 0/1 + let t37 = circuit_add(t29, t35); // Fp2 add coeff 1/1 + let t38 = circuit_add(t36, t37); + let t39 = circuit_add(t38, t38); + let t40 = circuit_sub(t36, t37); + let t41 = circuit_sub(t39, t36); + let t42 = circuit_sub(t41, t37); + let t43 = circuit_add(t40, in1); + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t43, t42, t9, t12,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in1 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(t0a0); // in2 + circuit_inputs = circuit_inputs.next_2(t0a1); // in3 + circuit_inputs = circuit_inputs.next_2(t1a0); // in4 + circuit_inputs = circuit_inputs.next_2(t1a1); // in5 + circuit_inputs = circuit_inputs.next_2(xc0b1a0); // in6 + circuit_inputs = circuit_inputs.next_2(xc0b1a1); // in7 + circuit_inputs = circuit_inputs.next_2(xc0b2a0); // in8 + circuit_inputs = circuit_inputs.next_2(xc0b2a1); // in9 + circuit_inputs = circuit_inputs.next_2(xc1b0a0); // in10 + circuit_inputs = circuit_inputs.next_2(xc1b0a1); // in11 + circuit_inputs = circuit_inputs.next_2(xc1b2a0); // in12 + circuit_inputs = circuit_inputs.next_2(xc1b2a1); // in13 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let zc0b0a0: u384 = outputs.get_output(t43); + let zc0b0a1: u384 = outputs.get_output(t42); + let zc1b1a0: u384 = outputs.get_output(t9); + let zc1b1a1: u384 = outputs.get_output(t12); + return (zc0b0a0, zc0b0a1, zc1b1a0, zc1b1a1); +} +#[inline(always)] +fn run_BLS12_381_E12T_DECOMP_KARABINA_I_NZ_circuit( + xc0b1a0: u384, + xc0b1a1: u384, + xc0b2a0: u384, + xc0b2a1: u384, + xc1b0a0: u384, + xc1b0a1: u384, + xc1b2a0: u384, + xc1b2a1: u384 +) -> (u384, u384, u384, u384) { + // INPUT stack + let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); + let (in3, in4, in5) = (CE::> {}, CE::> {}, CE::> {}); + let (in6, in7) = (CE::> {}, CE::> {}); + let t0 = circuit_add(in0, in1); + let t1 = circuit_sub(in0, in1); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in0, in1); + let t4 = circuit_add(t3, t3); + let t5 = circuit_sub(t2, in2); // Fp2 sub coeff 0/1 + let t6 = circuit_sub(t4, in3); // Fp2 sub coeff 1/1 + let t7 = circuit_add(t5, t5); // Fp2 add coeff 0/1 + let t8 = circuit_add(t6, t6); // Fp2 add coeff 1/1 + let t9 = circuit_add(t7, t2); // Fp2 add coeff 0/1 + let t10 = circuit_add(t8, t4); // Fp2 add coeff 1/1 + let t11 = circuit_add(in6, in7); + let t12 = circuit_sub(in6, in7); + let t13 = circuit_mul(t11, t12); + let t14 = circuit_mul(in6, in7); + let t15 = circuit_add(t14, t14); + let t16 = circuit_add(t13, t15); + let t17 = circuit_add(t16, t16); + let t18 = circuit_sub(t13, t15); + let t19 = circuit_sub(t17, t13); + let t20 = circuit_sub(t19, t15); + let t21 = circuit_add(t18, t9); // Fp2 add coeff 0/1 + let t22 = circuit_add(t20, t10); // Fp2 add coeff 1/1 + let t23 = circuit_add(in4, in4); // Fp2 add coeff 0/1 + let t24 = circuit_add(in5, in5); // Fp2 add coeff 1/1 + let t25 = circuit_add(t23, t23); // Fp2 add coeff 0/1 + let t26 = circuit_add(t24, t24); // Fp2 add coeff 1/1 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t21, t22, t25, t26,).new_inputs(); + // Prefill constants: + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(xc0b1a0); // in0 + circuit_inputs = circuit_inputs.next_2(xc0b1a1); // in1 + circuit_inputs = circuit_inputs.next_2(xc0b2a0); // in2 + circuit_inputs = circuit_inputs.next_2(xc0b2a1); // in3 + circuit_inputs = circuit_inputs.next_2(xc1b0a0); // in4 + circuit_inputs = circuit_inputs.next_2(xc1b0a1); // in5 + circuit_inputs = circuit_inputs.next_2(xc1b2a0); // in6 + circuit_inputs = circuit_inputs.next_2(xc1b2a1); // in7 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let t0a0: u384 = outputs.get_output(t21); + let t0a1: u384 = outputs.get_output(t22); + let t1a0: u384 = outputs.get_output(t25); + let t1a1: u384 = outputs.get_output(t26); + return (t0a0, t0a1, t1a0, t1a1); +} +#[inline(always)] +fn run_BLS12_381_E12T_DECOMP_KARABINA_I_Z_circuit( + xc0b1a0: u384, xc0b1a1: u384, xc1b2a0: u384, xc1b2a1: u384 +) -> (u384, u384) { + // INPUT stack + let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); + let in3 = CE::> {}; + let t0 = circuit_mul(in0, in2); // Fp2 mul start + let t1 = circuit_mul(in1, in3); + let t2 = circuit_sub(t0, t1); // Fp2 mul real part end + let t3 = circuit_mul(in0, in3); + let t4 = circuit_mul(in1, in2); + let t5 = circuit_add(t3, t4); // Fp2 mul imag part end + let t6 = circuit_add(t2, t2); // Fp2 add coeff 0/1 + let t7 = circuit_add(t5, t5); // Fp2 add coeff 1/1 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t6, t7,).new_inputs(); + // Prefill constants: + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(xc0b1a0); // in0 + circuit_inputs = circuit_inputs.next_2(xc0b1a1); // in1 + circuit_inputs = circuit_inputs.next_2(xc1b2a0); // in2 + circuit_inputs = circuit_inputs.next_2(xc1b2a1); // in3 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res0: u384 = outputs.get_output(t6); + let res1: u384 = outputs.get_output(t7); + return (res0, res1); +} +#[inline(always)] +fn run_BLS12_381_E12T_FROBENIUS_CUBE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x1 + let in2 = CE::> {}; // -0x1 % p + let in3 = CE::< + CI<3> + > {}; // 0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2 + let in4 = CE::< + CI<4> + > {}; // 0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09 + + // INPUT stack + let (in5, in6, in7) = (CE::> {}, CE::> {}, CE::> {}); + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in0, in6); + let t1 = circuit_add(in5, in0); + let t2 = circuit_sub(in0, in8); + let t3 = circuit_sub(in0, in10); + let t4 = circuit_sub(in0, in12); + let t5 = circuit_sub(in0, in14); + let t6 = circuit_sub(in0, in16); + let t7 = circuit_mul(in0, in7); // Fp2 mul start + let t8 = circuit_mul(in1, t2); + let t9 = circuit_sub(t7, t8); // Fp2 mul real part end + let t10 = circuit_mul(in0, t2); + let t11 = circuit_mul(in1, in7); + let t12 = circuit_add(t10, t11); // Fp2 mul imag part end + let t13 = circuit_mul(in2, in9); + let t14 = circuit_mul(in2, t3); + let t15 = circuit_mul(in3, in11); // Fp2 mul start + let t16 = circuit_mul(in4, t4); + let t17 = circuit_sub(t15, t16); // Fp2 mul real part end + let t18 = circuit_mul(in3, t4); + let t19 = circuit_mul(in4, in11); + let t20 = circuit_add(t18, t19); // Fp2 mul imag part end + let t21 = circuit_mul(in3, in13); // Fp2 mul start + let t22 = circuit_mul(in3, t5); + let t23 = circuit_sub(t21, t22); // Fp2 mul real part end + let t24 = circuit_mul(in3, t5); + let t25 = circuit_mul(in3, in13); + let t26 = circuit_add(t24, t25); // Fp2 mul imag part end + let t27 = circuit_mul(in4, in15); // Fp2 mul start + let t28 = circuit_mul(in3, t6); + let t29 = circuit_sub(t27, t28); // Fp2 mul real part end + let t30 = circuit_mul(in4, t6); + let t31 = circuit_mul(in3, in15); + let t32 = circuit_add(t30, t31); // Fp2 mul imag part end + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t1, t0, t9, t12, t13, t14, t17, t20, t23, t26, t29, t32,) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs + .next_2( + [ + 0xb153ffffb9feffffffffaaaa, + 0x6730d2a0f6b0f6241eabfffe, + 0x434bacd764774b84f38512bf, + 0x1a0111ea397fe69a4b1ba7b6 + ] + ); // in2 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x3e67fa0af1ee7b04121bdea2, + 0xef396489f61eb45e304466cf, + 0xd77a2cd91c3dedd930b1cf60, + 0x135203e60180a68ee2e9c448 + ] + ); // in3 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x72ec05f4c81084fbede3cc09, + 0x77f76e17009241c5ee67992f, + 0x6bd17ffe48395dabc2d3435e, + 0x6af0e0437ff400b6831e36d + ] + ); // in4 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in5 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in6 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in7 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in8 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in9 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in10 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in12 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in13 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in14 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in15 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in16 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t1), + c0b0a1: outputs.get_output(t0), + c0b1a0: outputs.get_output(t9), + c0b1a1: outputs.get_output(t12), + c0b2a0: outputs.get_output(t13), + c0b2a1: outputs.get_output(t14), + c1b0a0: outputs.get_output(t17), + c1b0a1: outputs.get_output(t20), + c1b1a0: outputs.get_output(t23), + c1b1a1: outputs.get_output(t26), + c1b2a0: outputs.get_output(t29), + c1b2a1: outputs.get_output(t32), + }; + return (res,); +} +#[inline(always)] +fn run_BLS12_381_E12T_FROBENIUS_SQUARE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::< + CI<1> + > {}; // 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe + let in2 = CE::< + CI<2> + > {}; // 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac + let in3 = CE::< + CI<3> + > {}; // 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff + let in4 = CE::> {}; // -0x1 % p + let in5 = CE::< + CI<5> + > {}; // 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad + + // INPUT stack + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let (in15, in16, in17) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in6, in0); + let t1 = circuit_add(in7, in0); + let t2 = circuit_mul(in1, in8); + let t3 = circuit_mul(in1, in9); + let t4 = circuit_mul(in2, in10); + let t5 = circuit_mul(in2, in11); + let t6 = circuit_mul(in3, in12); + let t7 = circuit_mul(in3, in13); + let t8 = circuit_mul(in4, in14); + let t9 = circuit_mul(in4, in15); + let t10 = circuit_mul(in5, in16); + let t11 = circuit_mul(in5, in17); + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x620a00022e01fffffffefffe, + 0xddb3a93be6f89688de17d813, + 0xdf76ce51ba69c6076a0f77ea, + 0x5f19672f + ] + ); // in1 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x4f49fffd8bfd00000000aaac, + 0x897d29650fb85f9b409427eb, + 0x63d4de85aa0d857d89759ad4, + 0x1a0111ea397fe699ec024086 + ] + ); // in2 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x620a00022e01fffffffeffff, + 0xddb3a93be6f89688de17d813, + 0xdf76ce51ba69c6076a0f77ea, + 0x5f19672f + ] + ); // in3 + circuit_inputs = circuit_inputs + .next_2( + [ + 0xb153ffffb9feffffffffaaaa, + 0x6730d2a0f6b0f6241eabfffe, + 0x434bacd764774b84f38512bf, + 0x1a0111ea397fe69a4b1ba7b6 + ] + ); // in4 + circuit_inputs = circuit_inputs + .next_2( + [ + 0x4f49fffd8bfd00000000aaad, + 0x897d29650fb85f9b409427eb, + 0x63d4de85aa0d857d89759ad4, + 0x1a0111ea397fe699ec024086 + ] + ); // in5 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in6 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in7 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in8 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in9 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in10 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in12 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in13 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in14 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in15 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in16 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in17 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t0), + c0b0a1: outputs.get_output(t1), + c0b1a0: outputs.get_output(t2), + c0b1a1: outputs.get_output(t3), + c0b2a0: outputs.get_output(t4), + c0b2a1: outputs.get_output(t5), + c1b0a0: outputs.get_output(t6), + c1b0a1: outputs.get_output(t7), + c1b1a0: outputs.get_output(t8), + c1b1a1: outputs.get_output(t9), + c1b2a0: outputs.get_output(t10), + c1b2a1: outputs.get_output(t11), + }; + return (res,); +} +#[inline(always)] +fn run_BLS12_381_E12T_FROBENIUS_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::< + CI<1> + > {}; // 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac + let in2 = CE::< + CI<2> + > {}; // 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad + let in3 = CE::< + CI<3> + > {}; // 0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8 + let in4 = CE::< + CI<4> + > {}; // 0xfc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3 + let in5 = CE::< + CI<5> + > {}; // 0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09 + let in6 = CE::< + CI<6> + > {}; // 0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116 + let in7 = CE::< + CI<7> + > {}; // 0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995 + + // INPUT stack + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let (in17, in18, in19) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in0, in9); + let t1 = circuit_add(in8, in0); + let t2 = circuit_sub(in0, in11); + let t3 = circuit_sub(in0, in13); + let t4 = circuit_sub(in0, in15); + let t5 = circuit_sub(in0, in17); + let t6 = circuit_sub(in0, in19); + let t7 = circuit_mul(in0, in10); // Fp2 mul start + let t8 = circuit_mul(in1, t2); + let t9 = circuit_sub(t7, t8); // Fp2 mul real part end + let t10 = circuit_mul(in0, t2); + let t11 = circuit_mul(in1, in10); + let t12 = circuit_add(t10, t11); // Fp2 mul imag part end + let t13 = circuit_mul(in2, in12); + let t14 = circuit_mul(in2, t3); + let t15 = circuit_mul(in3, in14); // Fp2 mul start + let t16 = circuit_mul(in4, t4); + let t17 = circuit_sub(t15, t16); // Fp2 mul real part end + let t18 = circuit_mul(in3, t4); + let t19 = circuit_mul(in4, in14); + let t20 = circuit_add(t18, t19); // Fp2 mul imag part end + let t21 = circuit_mul(in5, in16); // Fp2 mul start + let t22 = circuit_mul(in5, t5); + let t23 = circuit_sub(t21, t22); // Fp2 mul real part end + let t24 = circuit_mul(in5, t5); + let t25 = circuit_mul(in5, in16); + let t26 = circuit_add(t24, t25); // Fp2 mul imag part end + let t27 = circuit_mul(in6, in18); // Fp2 mul start + let t28 = circuit_mul(in7, t6); + let t29 = circuit_sub(t27, t28); // Fp2 mul real part end + let t30 = circuit_mul(in6, t6); + let t31 = circuit_mul(in7, in18); + let t32 = circuit_add(t30, t31); // Fp2 mul imag part end + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = (t1, t0, t9, t12, t13, t14, t17, t20, t23, t26, t29, t32,) + .new_inputs(); + // Prefill constants: + + circuit_inputs = circuit_inputs + .next_span(E12T_FROBENIUS_BLS12_381_CONSTANTS.span()); // in0 - in7 + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in8 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in9 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in10 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in11 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in12 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in13 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in14 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in15 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in16 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in17 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in18 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in19 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t1), + c0b0a1: outputs.get_output(t0), + c0b1a0: outputs.get_output(t9), + c0b1a1: outputs.get_output(t12), + c0b2a0: outputs.get_output(t13), + c0b2a1: outputs.get_output(t14), + c1b0a0: outputs.get_output(t17), + c1b0a1: outputs.get_output(t20), + c1b1a0: outputs.get_output(t23), + c1b1a1: outputs.get_output(t26), + c1b2a0: outputs.get_output(t29), + c1b2a1: outputs.get_output(t32), + }; + return (res,); +} +const E12T_FROBENIUS_BLS12_381_CONSTANTS: [ + u384 + ; 8] = [ + u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { + limb0: 0x4f49fffd8bfd00000000aaac, + limb1: 0x897d29650fb85f9b409427eb, + limb2: 0x63d4de85aa0d857d89759ad4, + limb3: 0x1a0111ea397fe699ec024086 + }, + u384 { + limb0: 0x4f49fffd8bfd00000000aaad, + limb1: 0x897d29650fb85f9b409427eb, + limb2: 0x63d4de85aa0d857d89759ad4, + limb3: 0x1a0111ea397fe699ec024086 + }, + u384 { + limb0: 0x63e7813d8d0775ed92235fb8, + limb1: 0x7b2443d784bab9c4f67ea53d, + limb2: 0x202c0d1f0fd603fd3cbd5f4f, + limb3: 0x1904d3bf02bb0667c231beb4 + }, + u384 { + limb0: 0x4d6c7ec22cf78a126ddc4af3, + limb1: 0xec0c8ec971f63c5f282d5ac1, + limb2: 0x231f9fb854a14787b6c7b36f, + limb3: 0xfc3e2b36c4e03288e9e902 + }, + u384 { + limb0: 0x72ec05f4c81084fbede3cc09, + limb1: 0x77f76e17009241c5ee67992f, + limb2: 0x6bd17ffe48395dabc2d3435e, + limb3: 0x6af0e0437ff400b6831e36d + }, + u384 { + limb0: 0x257f87329b18fae980078116, + limb1: 0x8beadf4d8e9c0566c63a3e6e, + limb2: 0x48b1e045f39816240c0b8fee, + limb3: 0x5b2cfd9013a5fd8df47fa6b + }, + u384 { + limb0: 0x8bd478cd1ee605167ff82995, + limb1: 0xdb45f3536814f0bd5871c190, + limb2: 0xfa99cc9170df3560e77982d0, + limb3: 0x144e4211384586c16bd3ad4a + } +]; +#[inline(always)] +fn run_BLS12_381_E12T_INVERSE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + + // INPUT stack + let (in1, in2, in3) = (CE::> {}, CE::> {}, CE::> {}); + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let (in7, in8, in9) = (CE::> {}, CE::> {}, CE::> {}); + let (in10, in11, in12) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_mul(in1, in3); // Fp2 mul start + let t1 = circuit_mul(in2, in4); + let t2 = circuit_sub(t0, t1); // Fp2 mul real part end + let t3 = circuit_mul(in1, in4); + let t4 = circuit_mul(in2, in3); + let t5 = circuit_add(t3, t4); // Fp2 mul imag part end + let t6 = circuit_add(t2, t2); // Fp2 add coeff 0/1 + let t7 = circuit_add(t5, t5); // Fp2 add coeff 1/1 + let t8 = circuit_add(in5, in6); + let t9 = circuit_sub(in5, in6); + let t10 = circuit_mul(t8, t9); + let t11 = circuit_mul(in5, in6); + let t12 = circuit_add(t11, t11); + let t13 = circuit_add(t10, t12); + let t14 = circuit_add(t13, t13); + let t15 = circuit_sub(t10, t12); + let t16 = circuit_sub(t14, t10); + let t17 = circuit_sub(t16, t12); + let t18 = circuit_add(t15, t6); // Fp2 add coeff 0/1 + let t19 = circuit_add(t17, t7); // Fp2 add coeff 1/1 + let t20 = circuit_sub(t6, t10); // Fp2 sub coeff 0/1 + let t21 = circuit_sub(t7, t12); // Fp2 sub coeff 1/1 + let t22 = circuit_add(in1, in2); + let t23 = circuit_sub(in1, in2); + let t24 = circuit_mul(t22, t23); + let t25 = circuit_mul(in1, in2); + let t26 = circuit_add(t25, t25); + let t27 = circuit_sub(in1, in3); // Fp2 sub coeff 0/1 + let t28 = circuit_sub(in2, in4); // Fp2 sub coeff 1/1 + let t29 = circuit_add(t27, in5); // Fp2 add coeff 0/1 + let t30 = circuit_add(t28, in6); // Fp2 add coeff 1/1 + let t31 = circuit_mul(in3, in5); // Fp2 mul start + let t32 = circuit_mul(in4, in6); + let t33 = circuit_sub(t31, t32); // Fp2 mul real part end + let t34 = circuit_mul(in3, in6); + let t35 = circuit_mul(in4, in5); + let t36 = circuit_add(t34, t35); // Fp2 mul imag part end + let t37 = circuit_add(t33, t33); // Fp2 add coeff 0/1 + let t38 = circuit_add(t36, t36); // Fp2 add coeff 1/1 + let t39 = circuit_add(t29, t30); + let t40 = circuit_sub(t29, t30); + let t41 = circuit_mul(t39, t40); + let t42 = circuit_mul(t29, t30); + let t43 = circuit_add(t42, t42); + let t44 = circuit_add(t37, t38); + let t45 = circuit_add(t44, t44); + let t46 = circuit_sub(t37, t38); + let t47 = circuit_sub(t45, t37); + let t48 = circuit_sub(t47, t38); + let t49 = circuit_add(t46, t24); // Fp2 add coeff 0/1 + let t50 = circuit_add(t48, t26); // Fp2 add coeff 1/1 + let t51 = circuit_add(t20, t41); // Fp2 add coeff 0/1 + let t52 = circuit_add(t21, t43); // Fp2 add coeff 1/1 + let t53 = circuit_add(t51, t37); // Fp2 add coeff 0/1 + let t54 = circuit_add(t52, t38); // Fp2 add coeff 1/1 + let t55 = circuit_sub(t53, t24); // Fp2 sub coeff 0/1 + let t56 = circuit_sub(t54, t26); // Fp2 sub coeff 1/1 + let t57 = circuit_mul(in7, in9); // Fp2 mul start + let t58 = circuit_mul(in8, in10); + let t59 = circuit_sub(t57, t58); // Fp2 mul real part end + let t60 = circuit_mul(in7, in10); + let t61 = circuit_mul(in8, in9); + let t62 = circuit_add(t60, t61); // Fp2 mul imag part end + let t63 = circuit_add(t59, t59); // Fp2 add coeff 0/1 + let t64 = circuit_add(t62, t62); // Fp2 add coeff 1/1 + let t65 = circuit_add(in11, in12); + let t66 = circuit_sub(in11, in12); + let t67 = circuit_mul(t65, t66); + let t68 = circuit_mul(in11, in12); + let t69 = circuit_add(t68, t68); + let t70 = circuit_add(t67, t69); + let t71 = circuit_add(t70, t70); + let t72 = circuit_sub(t67, t69); + let t73 = circuit_sub(t71, t67); + let t74 = circuit_sub(t73, t69); + let t75 = circuit_add(t72, t63); // Fp2 add coeff 0/1 + let t76 = circuit_add(t74, t64); // Fp2 add coeff 1/1 + let t77 = circuit_sub(t63, t67); // Fp2 sub coeff 0/1 + let t78 = circuit_sub(t64, t69); // Fp2 sub coeff 1/1 + let t79 = circuit_add(in7, in8); + let t80 = circuit_sub(in7, in8); + let t81 = circuit_mul(t79, t80); + let t82 = circuit_mul(in7, in8); + let t83 = circuit_add(t82, t82); + let t84 = circuit_sub(in7, in9); // Fp2 sub coeff 0/1 + let t85 = circuit_sub(in8, in10); // Fp2 sub coeff 1/1 + let t86 = circuit_add(t84, in11); // Fp2 add coeff 0/1 + let t87 = circuit_add(t85, in12); // Fp2 add coeff 1/1 + let t88 = circuit_mul(in9, in11); // Fp2 mul start + let t89 = circuit_mul(in10, in12); + let t90 = circuit_sub(t88, t89); // Fp2 mul real part end + let t91 = circuit_mul(in9, in12); + let t92 = circuit_mul(in10, in11); + let t93 = circuit_add(t91, t92); // Fp2 mul imag part end + let t94 = circuit_add(t90, t90); // Fp2 add coeff 0/1 + let t95 = circuit_add(t93, t93); // Fp2 add coeff 1/1 + let t96 = circuit_add(t86, t87); + let t97 = circuit_sub(t86, t87); + let t98 = circuit_mul(t96, t97); + let t99 = circuit_mul(t86, t87); + let t100 = circuit_add(t99, t99); + let t101 = circuit_add(t94, t95); + let t102 = circuit_add(t101, t101); + let t103 = circuit_sub(t94, t95); + let t104 = circuit_sub(t102, t94); + let t105 = circuit_sub(t104, t95); + let t106 = circuit_add(t103, t81); // Fp2 add coeff 0/1 + let t107 = circuit_add(t105, t83); // Fp2 add coeff 1/1 + let t108 = circuit_add(t77, t98); // Fp2 add coeff 0/1 + let t109 = circuit_add(t78, t100); // Fp2 add coeff 1/1 + let t110 = circuit_add(t108, t94); // Fp2 add coeff 0/1 + let t111 = circuit_add(t109, t95); // Fp2 add coeff 1/1 + let t112 = circuit_sub(t110, t81); // Fp2 sub coeff 0/1 + let t113 = circuit_sub(t111, t83); // Fp2 sub coeff 1/1 + let t114 = circuit_add(t112, t113); + let t115 = circuit_add(t114, t114); + let t116 = circuit_sub(t112, t113); + let t117 = circuit_sub(t115, t112); + let t118 = circuit_sub(t117, t113); + let t119 = circuit_sub(t49, t116); // Fp6 sub coeff 0/5 + let t120 = circuit_sub(t50, t118); // Fp6 sub coeff 1/5 + let t121 = circuit_sub(t18, t106); // Fp6 sub coeff 2/5 + let t122 = circuit_sub(t19, t107); // Fp6 sub coeff 3/5 + let t123 = circuit_sub(t55, t75); // Fp6 sub coeff 4/5 + let t124 = circuit_sub(t56, t76); // Fp6 sub coeff 5/5 + let t125 = circuit_add(t119, t120); + let t126 = circuit_sub(t119, t120); + let t127 = circuit_mul(t125, t126); + let t128 = circuit_mul(t119, t120); + let t129 = circuit_add(t128, t128); + let t130 = circuit_add(t121, t122); + let t131 = circuit_sub(t121, t122); + let t132 = circuit_mul(t130, t131); + let t133 = circuit_mul(t121, t122); + let t134 = circuit_add(t133, t133); + let t135 = circuit_add(t123, t124); + let t136 = circuit_sub(t123, t124); + let t137 = circuit_mul(t135, t136); + let t138 = circuit_mul(t123, t124); + let t139 = circuit_add(t138, t138); + let t140 = circuit_mul(t119, t121); // Fp2 mul start + let t141 = circuit_mul(t120, t122); + let t142 = circuit_sub(t140, t141); // Fp2 mul real part end + let t143 = circuit_mul(t119, t122); + let t144 = circuit_mul(t120, t121); + let t145 = circuit_add(t143, t144); // Fp2 mul imag part end + let t146 = circuit_mul(t119, t123); // Fp2 mul start + let t147 = circuit_mul(t120, t124); + let t148 = circuit_sub(t146, t147); // Fp2 mul real part end + let t149 = circuit_mul(t119, t124); + let t150 = circuit_mul(t120, t123); + let t151 = circuit_add(t149, t150); // Fp2 mul imag part end + let t152 = circuit_mul(t121, t123); // Fp2 mul start + let t153 = circuit_mul(t122, t124); + let t154 = circuit_sub(t152, t153); // Fp2 mul real part end + let t155 = circuit_mul(t121, t124); + let t156 = circuit_mul(t122, t123); + let t157 = circuit_add(t155, t156); // Fp2 mul imag part end + let t158 = circuit_add(t154, t157); + let t159 = circuit_add(t158, t158); + let t160 = circuit_sub(t154, t157); + let t161 = circuit_sub(t159, t154); + let t162 = circuit_sub(t161, t157); + let t163 = circuit_sub(in0, t160); // Fp2 neg coeff 0/1 + let t164 = circuit_sub(in0, t162); // Fp2 neg coeff 1/1 + let t165 = circuit_add(t163, t127); // Fp2 add coeff 0/1 + let t166 = circuit_add(t164, t129); // Fp2 add coeff 1/1 + let t167 = circuit_add(t137, t139); + let t168 = circuit_add(t167, t167); + let t169 = circuit_sub(t137, t139); + let t170 = circuit_sub(t168, t137); + let t171 = circuit_sub(t170, t139); + let t172 = circuit_sub(t169, t142); // Fp2 sub coeff 0/1 + let t173 = circuit_sub(t171, t145); // Fp2 sub coeff 1/1 + let t174 = circuit_sub(t132, t148); // Fp2 sub coeff 0/1 + let t175 = circuit_sub(t134, t151); // Fp2 sub coeff 1/1 + let t176 = circuit_mul(t119, t165); // Fp2 mul start + let t177 = circuit_mul(t120, t166); + let t178 = circuit_sub(t176, t177); // Fp2 mul real part end + let t179 = circuit_mul(t119, t166); + let t180 = circuit_mul(t120, t165); + let t181 = circuit_add(t179, t180); // Fp2 mul imag part end + let t182 = circuit_mul(t123, t172); // Fp2 mul start + let t183 = circuit_mul(t124, t173); + let t184 = circuit_sub(t182, t183); // Fp2 mul real part end + let t185 = circuit_mul(t123, t173); + let t186 = circuit_mul(t124, t172); + let t187 = circuit_add(t185, t186); // Fp2 mul imag part end + let t188 = circuit_mul(t121, t174); // Fp2 mul start + let t189 = circuit_mul(t122, t175); + let t190 = circuit_sub(t188, t189); // Fp2 mul real part end + let t191 = circuit_mul(t121, t175); + let t192 = circuit_mul(t122, t174); + let t193 = circuit_add(t191, t192); // Fp2 mul imag part end + let t194 = circuit_add(t184, t190); // Fp2 add coeff 0/1 + let t195 = circuit_add(t187, t193); // Fp2 add coeff 1/1 + let t196 = circuit_add(t194, t195); + let t197 = circuit_add(t196, t196); + let t198 = circuit_sub(t194, t195); + let t199 = circuit_sub(t197, t194); + let t200 = circuit_sub(t199, t195); + let t201 = circuit_add(t178, t198); // Fp2 add coeff 0/1 + let t202 = circuit_add(t181, t200); // Fp2 add coeff 1/1 + let t203 = circuit_mul(t201, t201); // Fp2 Inv start + let t204 = circuit_mul(t202, t202); + let t205 = circuit_add(t203, t204); + let t206 = circuit_inverse(t205); + let t207 = circuit_mul(t201, t206); // Fp2 Inv real part end + let t208 = circuit_mul(t202, t206); + let t209 = circuit_sub(in0, t208); // Fp2 Inv imag part end + let t210 = circuit_mul(t165, t207); // Fp2 mul start + let t211 = circuit_mul(t166, t209); + let t212 = circuit_sub(t210, t211); // Fp2 mul real part end + let t213 = circuit_mul(t165, t209); + let t214 = circuit_mul(t166, t207); + let t215 = circuit_add(t213, t214); // Fp2 mul imag part end + let t216 = circuit_mul(t172, t207); // Fp2 mul start + let t217 = circuit_mul(t173, t209); + let t218 = circuit_sub(t216, t217); // Fp2 mul real part end + let t219 = circuit_mul(t172, t209); + let t220 = circuit_mul(t173, t207); + let t221 = circuit_add(t219, t220); // Fp2 mul imag part end + let t222 = circuit_mul(t174, t207); // Fp2 mul start + let t223 = circuit_mul(t175, t209); + let t224 = circuit_sub(t222, t223); // Fp2 mul real part end + let t225 = circuit_mul(t174, t209); + let t226 = circuit_mul(t175, t207); + let t227 = circuit_add(t225, t226); // Fp2 mul imag part end + let t228 = circuit_mul(in1, t212); // Fp2 mul start + let t229 = circuit_mul(in2, t215); + let t230 = circuit_sub(t228, t229); // Fp2 mul real part end + let t231 = circuit_mul(in1, t215); + let t232 = circuit_mul(in2, t212); + let t233 = circuit_add(t231, t232); // Fp2 mul imag part end + let t234 = circuit_mul(in3, t218); // Fp2 mul start + let t235 = circuit_mul(in4, t221); + let t236 = circuit_sub(t234, t235); // Fp2 mul real part end + let t237 = circuit_mul(in3, t221); + let t238 = circuit_mul(in4, t218); + let t239 = circuit_add(t237, t238); // Fp2 mul imag part end + let t240 = circuit_mul(in5, t224); // Fp2 mul start + let t241 = circuit_mul(in6, t227); + let t242 = circuit_sub(t240, t241); // Fp2 mul real part end + let t243 = circuit_mul(in5, t227); + let t244 = circuit_mul(in6, t224); + let t245 = circuit_add(t243, t244); // Fp2 mul imag part end + let t246 = circuit_add(in3, in5); // Fp2 add coeff 0/1 + let t247 = circuit_add(in4, in6); // Fp2 add coeff 1/1 + let t248 = circuit_add(t218, t224); // Fp2 add coeff 0/1 + let t249 = circuit_add(t221, t227); // Fp2 add coeff 1/1 + let t250 = circuit_mul(t246, t248); // Fp2 mul start + let t251 = circuit_mul(t247, t249); + let t252 = circuit_sub(t250, t251); // Fp2 mul real part end + let t253 = circuit_mul(t246, t249); + let t254 = circuit_mul(t247, t248); + let t255 = circuit_add(t253, t254); // Fp2 mul imag part end + let t256 = circuit_sub(t252, t236); // Fp2 sub coeff 0/1 + let t257 = circuit_sub(t255, t239); // Fp2 sub coeff 1/1 + let t258 = circuit_sub(t256, t242); // Fp2 sub coeff 0/1 + let t259 = circuit_sub(t257, t245); // Fp2 sub coeff 1/1 + let t260 = circuit_add(t258, t259); + let t261 = circuit_add(t260, t260); + let t262 = circuit_sub(t258, t259); + let t263 = circuit_sub(t261, t258); + let t264 = circuit_sub(t263, t259); + let t265 = circuit_add(t262, t230); // Fp2 add coeff 0/1 + let t266 = circuit_add(t264, t233); // Fp2 add coeff 1/1 + let t267 = circuit_add(in1, in3); // Fp2 add coeff 0/1 + let t268 = circuit_add(in2, in4); // Fp2 add coeff 1/1 + let t269 = circuit_add(t212, t218); // Fp2 add coeff 0/1 + let t270 = circuit_add(t215, t221); // Fp2 add coeff 1/1 + let t271 = circuit_mul(t267, t269); // Fp2 mul start + let t272 = circuit_mul(t268, t270); + let t273 = circuit_sub(t271, t272); // Fp2 mul real part end + let t274 = circuit_mul(t267, t270); + let t275 = circuit_mul(t268, t269); + let t276 = circuit_add(t274, t275); // Fp2 mul imag part end + let t277 = circuit_sub(t273, t230); // Fp2 sub coeff 0/1 + let t278 = circuit_sub(t276, t233); // Fp2 sub coeff 1/1 + let t279 = circuit_sub(t277, t236); // Fp2 sub coeff 0/1 + let t280 = circuit_sub(t278, t239); // Fp2 sub coeff 1/1 + let t281 = circuit_add(t242, t245); + let t282 = circuit_add(t281, t281); + let t283 = circuit_sub(t242, t245); + let t284 = circuit_sub(t282, t242); + let t285 = circuit_sub(t284, t245); + let t286 = circuit_add(t279, t283); // Fp2 add coeff 0/1 + let t287 = circuit_add(t280, t285); // Fp2 add coeff 1/1 + let t288 = circuit_add(in1, in5); // Fp2 add coeff 0/1 + let t289 = circuit_add(in2, in6); // Fp2 add coeff 1/1 + let t290 = circuit_add(t212, t224); // Fp2 add coeff 0/1 + let t291 = circuit_add(t215, t227); // Fp2 add coeff 1/1 + let t292 = circuit_mul(t290, t288); // Fp2 mul start + let t293 = circuit_mul(t291, t289); + let t294 = circuit_sub(t292, t293); // Fp2 mul real part end + let t295 = circuit_mul(t290, t289); + let t296 = circuit_mul(t291, t288); + let t297 = circuit_add(t295, t296); // Fp2 mul imag part end + let t298 = circuit_sub(t294, t230); // Fp2 sub coeff 0/1 + let t299 = circuit_sub(t297, t233); // Fp2 sub coeff 1/1 + let t300 = circuit_sub(t298, t242); // Fp2 sub coeff 0/1 + let t301 = circuit_sub(t299, t245); // Fp2 sub coeff 1/1 + let t302 = circuit_add(t300, t236); // Fp2 add coeff 0/1 + let t303 = circuit_add(t301, t239); // Fp2 add coeff 1/1 + let t304 = circuit_mul(in7, t212); // Fp2 mul start + let t305 = circuit_mul(in8, t215); + let t306 = circuit_sub(t304, t305); // Fp2 mul real part end + let t307 = circuit_mul(in7, t215); + let t308 = circuit_mul(in8, t212); + let t309 = circuit_add(t307, t308); // Fp2 mul imag part end + let t310 = circuit_mul(in9, t218); // Fp2 mul start + let t311 = circuit_mul(in10, t221); + let t312 = circuit_sub(t310, t311); // Fp2 mul real part end + let t313 = circuit_mul(in9, t221); + let t314 = circuit_mul(in10, t218); + let t315 = circuit_add(t313, t314); // Fp2 mul imag part end + let t316 = circuit_mul(in11, t224); // Fp2 mul start + let t317 = circuit_mul(in12, t227); + let t318 = circuit_sub(t316, t317); // Fp2 mul real part end + let t319 = circuit_mul(in11, t227); + let t320 = circuit_mul(in12, t224); + let t321 = circuit_add(t319, t320); // Fp2 mul imag part end + let t322 = circuit_add(in9, in11); // Fp2 add coeff 0/1 + let t323 = circuit_add(in10, in12); // Fp2 add coeff 1/1 + let t324 = circuit_add(t218, t224); // Fp2 add coeff 0/1 + let t325 = circuit_add(t221, t227); // Fp2 add coeff 1/1 + let t326 = circuit_mul(t322, t324); // Fp2 mul start + let t327 = circuit_mul(t323, t325); + let t328 = circuit_sub(t326, t327); // Fp2 mul real part end + let t329 = circuit_mul(t322, t325); + let t330 = circuit_mul(t323, t324); + let t331 = circuit_add(t329, t330); // Fp2 mul imag part end + let t332 = circuit_sub(t328, t312); // Fp2 sub coeff 0/1 + let t333 = circuit_sub(t331, t315); // Fp2 sub coeff 1/1 + let t334 = circuit_sub(t332, t318); // Fp2 sub coeff 0/1 + let t335 = circuit_sub(t333, t321); // Fp2 sub coeff 1/1 + let t336 = circuit_add(t334, t335); + let t337 = circuit_add(t336, t336); + let t338 = circuit_sub(t334, t335); + let t339 = circuit_sub(t337, t334); + let t340 = circuit_sub(t339, t335); + let t341 = circuit_add(t338, t306); // Fp2 add coeff 0/1 + let t342 = circuit_add(t340, t309); // Fp2 add coeff 1/1 + let t343 = circuit_add(in7, in9); // Fp2 add coeff 0/1 + let t344 = circuit_add(in8, in10); // Fp2 add coeff 1/1 + let t345 = circuit_add(t212, t218); // Fp2 add coeff 0/1 + let t346 = circuit_add(t215, t221); // Fp2 add coeff 1/1 + let t347 = circuit_mul(t343, t345); // Fp2 mul start + let t348 = circuit_mul(t344, t346); + let t349 = circuit_sub(t347, t348); // Fp2 mul real part end + let t350 = circuit_mul(t343, t346); + let t351 = circuit_mul(t344, t345); + let t352 = circuit_add(t350, t351); // Fp2 mul imag part end + let t353 = circuit_sub(t349, t306); // Fp2 sub coeff 0/1 + let t354 = circuit_sub(t352, t309); // Fp2 sub coeff 1/1 + let t355 = circuit_sub(t353, t312); // Fp2 sub coeff 0/1 + let t356 = circuit_sub(t354, t315); // Fp2 sub coeff 1/1 + let t357 = circuit_add(t318, t321); + let t358 = circuit_add(t357, t357); + let t359 = circuit_sub(t318, t321); + let t360 = circuit_sub(t358, t318); + let t361 = circuit_sub(t360, t321); + let t362 = circuit_add(t355, t359); // Fp2 add coeff 0/1 + let t363 = circuit_add(t356, t361); // Fp2 add coeff 1/1 + let t364 = circuit_add(in7, in11); // Fp2 add coeff 0/1 + let t365 = circuit_add(in8, in12); // Fp2 add coeff 1/1 + let t366 = circuit_add(t212, t224); // Fp2 add coeff 0/1 + let t367 = circuit_add(t215, t227); // Fp2 add coeff 1/1 + let t368 = circuit_mul(t366, t364); // Fp2 mul start + let t369 = circuit_mul(t367, t365); + let t370 = circuit_sub(t368, t369); // Fp2 mul real part end + let t371 = circuit_mul(t366, t365); + let t372 = circuit_mul(t367, t364); + let t373 = circuit_add(t371, t372); // Fp2 mul imag part end + let t374 = circuit_sub(t370, t306); // Fp2 sub coeff 0/1 + let t375 = circuit_sub(t373, t309); // Fp2 sub coeff 1/1 + let t376 = circuit_sub(t374, t318); // Fp2 sub coeff 0/1 + let t377 = circuit_sub(t375, t321); // Fp2 sub coeff 1/1 + let t378 = circuit_add(t376, t312); // Fp2 add coeff 0/1 + let t379 = circuit_add(t377, t315); // Fp2 add coeff 1/1 + let t380 = circuit_sub(in0, t341); // Fp6 neg coeff 0/5 + let t381 = circuit_sub(in0, t342); // Fp6 neg coeff 1/5 + let t382 = circuit_sub(in0, t362); // Fp6 neg coeff 2/5 + let t383 = circuit_sub(in0, t363); // Fp6 neg coeff 3/5 + let t384 = circuit_sub(in0, t378); // Fp6 neg coeff 4/5 + let t385 = circuit_sub(in0, t379); // Fp6 neg coeff 5/5 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = ( + t265, t266, t286, t287, t302, t303, t380, t381, t382, t383, t384, t385, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in1 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in2 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in3 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in4 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in5 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in6 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in7 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in8 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in9 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in10 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in12 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t265), + c0b0a1: outputs.get_output(t266), + c0b1a0: outputs.get_output(t286), + c0b1a1: outputs.get_output(t287), + c0b2a0: outputs.get_output(t302), + c0b2a1: outputs.get_output(t303), + c1b0a0: outputs.get_output(t380), + c1b0a1: outputs.get_output(t381), + c1b1a0: outputs.get_output(t382), + c1b1a1: outputs.get_output(t383), + c1b2a0: outputs.get_output(t384), + c1b2a1: outputs.get_output(t385), + }; + return (res,); +} +#[inline(always)] +fn run_BLS12_381_E12T_MUL_circuit(X: E12T, Y: E12T) -> (E12T,) { + // INPUT stack + let (in0, in1, in2) = (CE::> {}, CE::> {}, CE::> {}); + let (in3, in4, in5) = (CE::> {}, CE::> {}, CE::> {}); + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let (in15, in16, in17) = (CE::> {}, CE::> {}, CE::> {}); + let (in18, in19, in20) = (CE::> {}, CE::> {}, CE::> {}); + let (in21, in22, in23) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in0, in6); // Fp6 add coeff 0/5 + let t1 = circuit_add(in1, in7); // Fp6 add coeff 1/5 + let t2 = circuit_add(in2, in8); // Fp6 add coeff 2/5 + let t3 = circuit_add(in3, in9); // Fp6 add coeff 3/5 + let t4 = circuit_add(in4, in10); // Fp6 add coeff 4/5 + let t5 = circuit_add(in5, in11); // Fp6 add coeff 5/5 + let t6 = circuit_add(in12, in18); // Fp6 add coeff 0/5 + let t7 = circuit_add(in13, in19); // Fp6 add coeff 1/5 + let t8 = circuit_add(in14, in20); // Fp6 add coeff 2/5 + let t9 = circuit_add(in15, in21); // Fp6 add coeff 3/5 + let t10 = circuit_add(in16, in22); // Fp6 add coeff 4/5 + let t11 = circuit_add(in17, in23); // Fp6 add coeff 5/5 + let t12 = circuit_mul(t0, t6); // Fp2 mul start + let t13 = circuit_mul(t1, t7); + let t14 = circuit_sub(t12, t13); // Fp2 mul real part end + let t15 = circuit_mul(t0, t7); + let t16 = circuit_mul(t1, t6); + let t17 = circuit_add(t15, t16); // Fp2 mul imag part end + let t18 = circuit_mul(t2, t8); // Fp2 mul start + let t19 = circuit_mul(t3, t9); + let t20 = circuit_sub(t18, t19); // Fp2 mul real part end + let t21 = circuit_mul(t2, t9); + let t22 = circuit_mul(t3, t8); + let t23 = circuit_add(t21, t22); // Fp2 mul imag part end + let t24 = circuit_mul(t4, t10); // Fp2 mul start + let t25 = circuit_mul(t5, t11); + let t26 = circuit_sub(t24, t25); // Fp2 mul real part end + let t27 = circuit_mul(t4, t11); + let t28 = circuit_mul(t5, t10); + let t29 = circuit_add(t27, t28); // Fp2 mul imag part end + let t30 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t31 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t32 = circuit_add(t8, t10); // Fp2 add coeff 0/1 + let t33 = circuit_add(t9, t11); // Fp2 add coeff 1/1 + let t34 = circuit_mul(t30, t32); // Fp2 mul start + let t35 = circuit_mul(t31, t33); + let t36 = circuit_sub(t34, t35); // Fp2 mul real part end + let t37 = circuit_mul(t30, t33); + let t38 = circuit_mul(t31, t32); + let t39 = circuit_add(t37, t38); // Fp2 mul imag part end + let t40 = circuit_sub(t36, t20); // Fp2 sub coeff 0/1 + let t41 = circuit_sub(t39, t23); // Fp2 sub coeff 1/1 + let t42 = circuit_sub(t40, t26); // Fp2 sub coeff 0/1 + let t43 = circuit_sub(t41, t29); // Fp2 sub coeff 1/1 + let t44 = circuit_add(t42, t43); + let t45 = circuit_add(t44, t44); + let t46 = circuit_sub(t42, t43); + let t47 = circuit_sub(t45, t42); + let t48 = circuit_sub(t47, t43); + let t49 = circuit_add(t46, t14); // Fp2 add coeff 0/1 + let t50 = circuit_add(t48, t17); // Fp2 add coeff 1/1 + let t51 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t52 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t53 = circuit_add(t6, t8); // Fp2 add coeff 0/1 + let t54 = circuit_add(t7, t9); // Fp2 add coeff 1/1 + let t55 = circuit_mul(t51, t53); // Fp2 mul start + let t56 = circuit_mul(t52, t54); + let t57 = circuit_sub(t55, t56); // Fp2 mul real part end + let t58 = circuit_mul(t51, t54); + let t59 = circuit_mul(t52, t53); + let t60 = circuit_add(t58, t59); // Fp2 mul imag part end + let t61 = circuit_sub(t57, t14); // Fp2 sub coeff 0/1 + let t62 = circuit_sub(t60, t17); // Fp2 sub coeff 1/1 + let t63 = circuit_sub(t61, t20); // Fp2 sub coeff 0/1 + let t64 = circuit_sub(t62, t23); // Fp2 sub coeff 1/1 + let t65 = circuit_add(t26, t29); + let t66 = circuit_add(t65, t65); + let t67 = circuit_sub(t26, t29); + let t68 = circuit_sub(t66, t26); + let t69 = circuit_sub(t68, t29); + let t70 = circuit_add(t63, t67); // Fp2 add coeff 0/1 + let t71 = circuit_add(t64, t69); // Fp2 add coeff 1/1 + let t72 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t73 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t74 = circuit_add(t6, t10); // Fp2 add coeff 0/1 + let t75 = circuit_add(t7, t11); // Fp2 add coeff 1/1 + let t76 = circuit_mul(t74, t72); // Fp2 mul start + let t77 = circuit_mul(t75, t73); + let t78 = circuit_sub(t76, t77); // Fp2 mul real part end + let t79 = circuit_mul(t74, t73); + let t80 = circuit_mul(t75, t72); + let t81 = circuit_add(t79, t80); // Fp2 mul imag part end + let t82 = circuit_sub(t78, t14); // Fp2 sub coeff 0/1 + let t83 = circuit_sub(t81, t17); // Fp2 sub coeff 1/1 + let t84 = circuit_sub(t82, t26); // Fp2 sub coeff 0/1 + let t85 = circuit_sub(t83, t29); // Fp2 sub coeff 1/1 + let t86 = circuit_add(t84, t20); // Fp2 add coeff 0/1 + let t87 = circuit_add(t85, t23); // Fp2 add coeff 1/1 + let t88 = circuit_mul(in0, in12); // Fp2 mul start + let t89 = circuit_mul(in1, in13); + let t90 = circuit_sub(t88, t89); // Fp2 mul real part end + let t91 = circuit_mul(in0, in13); + let t92 = circuit_mul(in1, in12); + let t93 = circuit_add(t91, t92); // Fp2 mul imag part end + let t94 = circuit_mul(in2, in14); // Fp2 mul start + let t95 = circuit_mul(in3, in15); + let t96 = circuit_sub(t94, t95); // Fp2 mul real part end + let t97 = circuit_mul(in2, in15); + let t98 = circuit_mul(in3, in14); + let t99 = circuit_add(t97, t98); // Fp2 mul imag part end + let t100 = circuit_mul(in4, in16); // Fp2 mul start + let t101 = circuit_mul(in5, in17); + let t102 = circuit_sub(t100, t101); // Fp2 mul real part end + let t103 = circuit_mul(in4, in17); + let t104 = circuit_mul(in5, in16); + let t105 = circuit_add(t103, t104); // Fp2 mul imag part end + let t106 = circuit_add(in2, in4); // Fp2 add coeff 0/1 + let t107 = circuit_add(in3, in5); // Fp2 add coeff 1/1 + let t108 = circuit_add(in14, in16); // Fp2 add coeff 0/1 + let t109 = circuit_add(in15, in17); // Fp2 add coeff 1/1 + let t110 = circuit_mul(t106, t108); // Fp2 mul start + let t111 = circuit_mul(t107, t109); + let t112 = circuit_sub(t110, t111); // Fp2 mul real part end + let t113 = circuit_mul(t106, t109); + let t114 = circuit_mul(t107, t108); + let t115 = circuit_add(t113, t114); // Fp2 mul imag part end + let t116 = circuit_sub(t112, t96); // Fp2 sub coeff 0/1 + let t117 = circuit_sub(t115, t99); // Fp2 sub coeff 1/1 + let t118 = circuit_sub(t116, t102); // Fp2 sub coeff 0/1 + let t119 = circuit_sub(t117, t105); // Fp2 sub coeff 1/1 + let t120 = circuit_add(t118, t119); + let t121 = circuit_add(t120, t120); + let t122 = circuit_sub(t118, t119); + let t123 = circuit_sub(t121, t118); + let t124 = circuit_sub(t123, t119); + let t125 = circuit_add(t122, t90); // Fp2 add coeff 0/1 + let t126 = circuit_add(t124, t93); // Fp2 add coeff 1/1 + let t127 = circuit_add(in0, in2); // Fp2 add coeff 0/1 + let t128 = circuit_add(in1, in3); // Fp2 add coeff 1/1 + let t129 = circuit_add(in12, in14); // Fp2 add coeff 0/1 + let t130 = circuit_add(in13, in15); // Fp2 add coeff 1/1 + let t131 = circuit_mul(t127, t129); // Fp2 mul start + let t132 = circuit_mul(t128, t130); + let t133 = circuit_sub(t131, t132); // Fp2 mul real part end + let t134 = circuit_mul(t127, t130); + let t135 = circuit_mul(t128, t129); + let t136 = circuit_add(t134, t135); // Fp2 mul imag part end + let t137 = circuit_sub(t133, t90); // Fp2 sub coeff 0/1 + let t138 = circuit_sub(t136, t93); // Fp2 sub coeff 1/1 + let t139 = circuit_sub(t137, t96); // Fp2 sub coeff 0/1 + let t140 = circuit_sub(t138, t99); // Fp2 sub coeff 1/1 + let t141 = circuit_add(t102, t105); + let t142 = circuit_add(t141, t141); + let t143 = circuit_sub(t102, t105); + let t144 = circuit_sub(t142, t102); + let t145 = circuit_sub(t144, t105); + let t146 = circuit_add(t139, t143); // Fp2 add coeff 0/1 + let t147 = circuit_add(t140, t145); // Fp2 add coeff 1/1 + let t148 = circuit_add(in0, in4); // Fp2 add coeff 0/1 + let t149 = circuit_add(in1, in5); // Fp2 add coeff 1/1 + let t150 = circuit_add(in12, in16); // Fp2 add coeff 0/1 + let t151 = circuit_add(in13, in17); // Fp2 add coeff 1/1 + let t152 = circuit_mul(t150, t148); // Fp2 mul start + let t153 = circuit_mul(t151, t149); + let t154 = circuit_sub(t152, t153); // Fp2 mul real part end + let t155 = circuit_mul(t150, t149); + let t156 = circuit_mul(t151, t148); + let t157 = circuit_add(t155, t156); // Fp2 mul imag part end + let t158 = circuit_sub(t154, t90); // Fp2 sub coeff 0/1 + let t159 = circuit_sub(t157, t93); // Fp2 sub coeff 1/1 + let t160 = circuit_sub(t158, t102); // Fp2 sub coeff 0/1 + let t161 = circuit_sub(t159, t105); // Fp2 sub coeff 1/1 + let t162 = circuit_add(t160, t96); // Fp2 add coeff 0/1 + let t163 = circuit_add(t161, t99); // Fp2 add coeff 1/1 + let t164 = circuit_mul(in6, in18); // Fp2 mul start + let t165 = circuit_mul(in7, in19); + let t166 = circuit_sub(t164, t165); // Fp2 mul real part end + let t167 = circuit_mul(in6, in19); + let t168 = circuit_mul(in7, in18); + let t169 = circuit_add(t167, t168); // Fp2 mul imag part end + let t170 = circuit_mul(in8, in20); // Fp2 mul start + let t171 = circuit_mul(in9, in21); + let t172 = circuit_sub(t170, t171); // Fp2 mul real part end + let t173 = circuit_mul(in8, in21); + let t174 = circuit_mul(in9, in20); + let t175 = circuit_add(t173, t174); // Fp2 mul imag part end + let t176 = circuit_mul(in10, in22); // Fp2 mul start + let t177 = circuit_mul(in11, in23); + let t178 = circuit_sub(t176, t177); // Fp2 mul real part end + let t179 = circuit_mul(in10, in23); + let t180 = circuit_mul(in11, in22); + let t181 = circuit_add(t179, t180); // Fp2 mul imag part end + let t182 = circuit_add(in8, in10); // Fp2 add coeff 0/1 + let t183 = circuit_add(in9, in11); // Fp2 add coeff 1/1 + let t184 = circuit_add(in20, in22); // Fp2 add coeff 0/1 + let t185 = circuit_add(in21, in23); // Fp2 add coeff 1/1 + let t186 = circuit_mul(t182, t184); // Fp2 mul start + let t187 = circuit_mul(t183, t185); + let t188 = circuit_sub(t186, t187); // Fp2 mul real part end + let t189 = circuit_mul(t182, t185); + let t190 = circuit_mul(t183, t184); + let t191 = circuit_add(t189, t190); // Fp2 mul imag part end + let t192 = circuit_sub(t188, t172); // Fp2 sub coeff 0/1 + let t193 = circuit_sub(t191, t175); // Fp2 sub coeff 1/1 + let t194 = circuit_sub(t192, t178); // Fp2 sub coeff 0/1 + let t195 = circuit_sub(t193, t181); // Fp2 sub coeff 1/1 + let t196 = circuit_add(t194, t195); + let t197 = circuit_add(t196, t196); + let t198 = circuit_sub(t194, t195); + let t199 = circuit_sub(t197, t194); + let t200 = circuit_sub(t199, t195); + let t201 = circuit_add(t198, t166); // Fp2 add coeff 0/1 + let t202 = circuit_add(t200, t169); // Fp2 add coeff 1/1 + let t203 = circuit_add(in6, in8); // Fp2 add coeff 0/1 + let t204 = circuit_add(in7, in9); // Fp2 add coeff 1/1 + let t205 = circuit_add(in18, in20); // Fp2 add coeff 0/1 + let t206 = circuit_add(in19, in21); // Fp2 add coeff 1/1 + let t207 = circuit_mul(t203, t205); // Fp2 mul start + let t208 = circuit_mul(t204, t206); + let t209 = circuit_sub(t207, t208); // Fp2 mul real part end + let t210 = circuit_mul(t203, t206); + let t211 = circuit_mul(t204, t205); + let t212 = circuit_add(t210, t211); // Fp2 mul imag part end + let t213 = circuit_sub(t209, t166); // Fp2 sub coeff 0/1 + let t214 = circuit_sub(t212, t169); // Fp2 sub coeff 1/1 + let t215 = circuit_sub(t213, t172); // Fp2 sub coeff 0/1 + let t216 = circuit_sub(t214, t175); // Fp2 sub coeff 1/1 + let t217 = circuit_add(t178, t181); + let t218 = circuit_add(t217, t217); + let t219 = circuit_sub(t178, t181); + let t220 = circuit_sub(t218, t178); + let t221 = circuit_sub(t220, t181); + let t222 = circuit_add(t215, t219); // Fp2 add coeff 0/1 + let t223 = circuit_add(t216, t221); // Fp2 add coeff 1/1 + let t224 = circuit_add(in6, in10); // Fp2 add coeff 0/1 + let t225 = circuit_add(in7, in11); // Fp2 add coeff 1/1 + let t226 = circuit_add(in18, in22); // Fp2 add coeff 0/1 + let t227 = circuit_add(in19, in23); // Fp2 add coeff 1/1 + let t228 = circuit_mul(t226, t224); // Fp2 mul start + let t229 = circuit_mul(t227, t225); + let t230 = circuit_sub(t228, t229); // Fp2 mul real part end + let t231 = circuit_mul(t226, t225); + let t232 = circuit_mul(t227, t224); + let t233 = circuit_add(t231, t232); // Fp2 mul imag part end + let t234 = circuit_sub(t230, t166); // Fp2 sub coeff 0/1 + let t235 = circuit_sub(t233, t169); // Fp2 sub coeff 1/1 + let t236 = circuit_sub(t234, t178); // Fp2 sub coeff 0/1 + let t237 = circuit_sub(t235, t181); // Fp2 sub coeff 1/1 + let t238 = circuit_add(t236, t172); // Fp2 add coeff 0/1 + let t239 = circuit_add(t237, t175); // Fp2 add coeff 1/1 + let t240 = circuit_sub(t49, t125); // Fp6 sub coeff 0/5 + let t241 = circuit_sub(t50, t126); // Fp6 sub coeff 1/5 + let t242 = circuit_sub(t70, t146); // Fp6 sub coeff 2/5 + let t243 = circuit_sub(t71, t147); // Fp6 sub coeff 3/5 + let t244 = circuit_sub(t86, t162); // Fp6 sub coeff 4/5 + let t245 = circuit_sub(t87, t163); // Fp6 sub coeff 5/5 + let t246 = circuit_sub(t240, t201); // Fp6 sub coeff 0/5 + let t247 = circuit_sub(t241, t202); // Fp6 sub coeff 1/5 + let t248 = circuit_sub(t242, t222); // Fp6 sub coeff 2/5 + let t249 = circuit_sub(t243, t223); // Fp6 sub coeff 3/5 + let t250 = circuit_sub(t244, t238); // Fp6 sub coeff 4/5 + let t251 = circuit_sub(t245, t239); // Fp6 sub coeff 5/5 + let t252 = circuit_add(t238, t239); + let t253 = circuit_add(t252, t252); + let t254 = circuit_sub(t238, t239); + let t255 = circuit_sub(t253, t238); + let t256 = circuit_sub(t255, t239); + let t257 = circuit_add(t254, t125); // Fp6 add coeff 0/5 + let t258 = circuit_add(t256, t126); // Fp6 add coeff 1/5 + let t259 = circuit_add(t201, t146); // Fp6 add coeff 2/5 + let t260 = circuit_add(t202, t147); // Fp6 add coeff 3/5 + let t261 = circuit_add(t222, t162); // Fp6 add coeff 4/5 + let t262 = circuit_add(t223, t163); // Fp6 add coeff 5/5 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = ( + t257, t258, t259, t260, t261, t262, t246, t247, t248, t249, t250, t251, + ) + .new_inputs(); + // Prefill constants: + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(X.c0b0a0); // in0 + circuit_inputs = circuit_inputs.next_2(X.c0b0a1); // in1 + circuit_inputs = circuit_inputs.next_2(X.c0b1a0); // in2 + circuit_inputs = circuit_inputs.next_2(X.c0b1a1); // in3 + circuit_inputs = circuit_inputs.next_2(X.c0b2a0); // in4 + circuit_inputs = circuit_inputs.next_2(X.c0b2a1); // in5 + circuit_inputs = circuit_inputs.next_2(X.c1b0a0); // in6 + circuit_inputs = circuit_inputs.next_2(X.c1b0a1); // in7 + circuit_inputs = circuit_inputs.next_2(X.c1b1a0); // in8 + circuit_inputs = circuit_inputs.next_2(X.c1b1a1); // in9 + circuit_inputs = circuit_inputs.next_2(X.c1b2a0); // in10 + circuit_inputs = circuit_inputs.next_2(X.c1b2a1); // in11 + circuit_inputs = circuit_inputs.next_2(Y.c0b0a0); // in12 + circuit_inputs = circuit_inputs.next_2(Y.c0b0a1); // in13 + circuit_inputs = circuit_inputs.next_2(Y.c0b1a0); // in14 + circuit_inputs = circuit_inputs.next_2(Y.c0b1a1); // in15 + circuit_inputs = circuit_inputs.next_2(Y.c0b2a0); // in16 + circuit_inputs = circuit_inputs.next_2(Y.c0b2a1); // in17 + circuit_inputs = circuit_inputs.next_2(Y.c1b0a0); // in18 + circuit_inputs = circuit_inputs.next_2(Y.c1b0a1); // in19 + circuit_inputs = circuit_inputs.next_2(Y.c1b1a0); // in20 + circuit_inputs = circuit_inputs.next_2(Y.c1b1a1); // in21 + circuit_inputs = circuit_inputs.next_2(Y.c1b2a0); // in22 + circuit_inputs = circuit_inputs.next_2(Y.c1b2a1); // in23 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t257), + c0b0a1: outputs.get_output(t258), + c0b1a0: outputs.get_output(t259), + c0b1a1: outputs.get_output(t260), + c0b2a0: outputs.get_output(t261), + c0b2a1: outputs.get_output(t262), + c1b0a0: outputs.get_output(t246), + c1b0a1: outputs.get_output(t247), + c1b1a0: outputs.get_output(t248), + c1b1a1: outputs.get_output(t249), + c1b2a0: outputs.get_output(t250), + c1b2a1: outputs.get_output(t251), + }; + return (res,); +} +#[inline(always)] +fn run_BLS12_381_TOWER_MILLER_BIT0_1P_circuit( + yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point, M_i: E12T +) -> (G2Point, E12T) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x3 + let in2 = CE::> {}; // 0x6 + let in3 = CE::> {}; // 0x1 + + // INPUT stack + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let (in7, in8, in9) = (CE::> {}, CE::> {}, CE::> {}); + let (in10, in11, in12) = (CE::> {}, CE::> {}, CE::> {}); + let (in13, in14, in15) = (CE::> {}, CE::> {}, CE::> {}); + let (in16, in17, in18) = (CE::> {}, CE::> {}, CE::> {}); + let (in19, in20, in21) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in10, in16); // Fp6 sub coeff 0/5 + let t1 = circuit_sub(in11, in17); // Fp6 sub coeff 1/5 + let t2 = circuit_sub(in12, in18); // Fp6 sub coeff 2/5 + let t3 = circuit_sub(in13, in19); // Fp6 sub coeff 3/5 + let t4 = circuit_sub(in14, in20); // Fp6 sub coeff 4/5 + let t5 = circuit_sub(in15, in21); // Fp6 sub coeff 5/5 + let t6 = circuit_add(in20, in21); + let t7 = circuit_add(t6, t6); + let t8 = circuit_sub(in20, in21); + let t9 = circuit_sub(t7, in20); + let t10 = circuit_sub(t9, in21); + let t11 = circuit_sub(in0, t8); // Fp6 neg coeff 0/5 + let t12 = circuit_sub(in0, t10); // Fp6 neg coeff 1/5 + let t13 = circuit_sub(in0, in16); // Fp6 neg coeff 2/5 + let t14 = circuit_sub(in0, in17); // Fp6 neg coeff 3/5 + let t15 = circuit_sub(in0, in18); // Fp6 neg coeff 4/5 + let t16 = circuit_sub(in0, in19); // Fp6 neg coeff 5/5 + let t17 = circuit_add(in10, t11); // Fp6 add coeff 0/5 + let t18 = circuit_add(in11, t12); // Fp6 add coeff 1/5 + let t19 = circuit_add(in12, t13); // Fp6 add coeff 2/5 + let t20 = circuit_add(in13, t14); // Fp6 add coeff 3/5 + let t21 = circuit_add(in14, t15); // Fp6 add coeff 4/5 + let t22 = circuit_add(in15, t16); // Fp6 add coeff 5/5 + let t23 = circuit_mul(in10, in16); // Fp2 mul start + let t24 = circuit_mul(in11, in17); + let t25 = circuit_sub(t23, t24); // Fp2 mul real part end + let t26 = circuit_mul(in10, in17); + let t27 = circuit_mul(in11, in16); + let t28 = circuit_add(t26, t27); // Fp2 mul imag part end + let t29 = circuit_mul(in12, in18); // Fp2 mul start + let t30 = circuit_mul(in13, in19); + let t31 = circuit_sub(t29, t30); // Fp2 mul real part end + let t32 = circuit_mul(in12, in19); + let t33 = circuit_mul(in13, in18); + let t34 = circuit_add(t32, t33); // Fp2 mul imag part end + let t35 = circuit_mul(in14, in20); // Fp2 mul start + let t36 = circuit_mul(in15, in21); + let t37 = circuit_sub(t35, t36); // Fp2 mul real part end + let t38 = circuit_mul(in14, in21); + let t39 = circuit_mul(in15, in20); + let t40 = circuit_add(t38, t39); // Fp2 mul imag part end + let t41 = circuit_add(in12, in14); // Fp2 add coeff 0/1 + let t42 = circuit_add(in13, in15); // Fp2 add coeff 1/1 + let t43 = circuit_add(in18, in20); // Fp2 add coeff 0/1 + let t44 = circuit_add(in19, in21); // Fp2 add coeff 1/1 + let t45 = circuit_mul(t41, t43); // Fp2 mul start + let t46 = circuit_mul(t42, t44); + let t47 = circuit_sub(t45, t46); // Fp2 mul real part end + let t48 = circuit_mul(t41, t44); + let t49 = circuit_mul(t42, t43); + let t50 = circuit_add(t48, t49); // Fp2 mul imag part end + let t51 = circuit_sub(t47, t31); // Fp2 sub coeff 0/1 + let t52 = circuit_sub(t50, t34); // Fp2 sub coeff 1/1 + let t53 = circuit_sub(t51, t37); // Fp2 sub coeff 0/1 + let t54 = circuit_sub(t52, t40); // Fp2 sub coeff 1/1 + let t55 = circuit_add(t53, t54); + let t56 = circuit_add(t55, t55); + let t57 = circuit_sub(t53, t54); + let t58 = circuit_sub(t56, t53); + let t59 = circuit_sub(t58, t54); + let t60 = circuit_add(t57, t25); // Fp2 add coeff 0/1 + let t61 = circuit_add(t59, t28); // Fp2 add coeff 1/1 + let t62 = circuit_add(in10, in12); // Fp2 add coeff 0/1 + let t63 = circuit_add(in11, in13); // Fp2 add coeff 1/1 + let t64 = circuit_add(in16, in18); // Fp2 add coeff 0/1 + let t65 = circuit_add(in17, in19); // Fp2 add coeff 1/1 + let t66 = circuit_mul(t62, t64); // Fp2 mul start + let t67 = circuit_mul(t63, t65); + let t68 = circuit_sub(t66, t67); // Fp2 mul real part end + let t69 = circuit_mul(t62, t65); + let t70 = circuit_mul(t63, t64); + let t71 = circuit_add(t69, t70); // Fp2 mul imag part end + let t72 = circuit_sub(t68, t25); // Fp2 sub coeff 0/1 + let t73 = circuit_sub(t71, t28); // Fp2 sub coeff 1/1 + let t74 = circuit_sub(t72, t31); // Fp2 sub coeff 0/1 + let t75 = circuit_sub(t73, t34); // Fp2 sub coeff 1/1 + let t76 = circuit_add(t37, t40); + let t77 = circuit_add(t76, t76); + let t78 = circuit_sub(t37, t40); + let t79 = circuit_sub(t77, t37); + let t80 = circuit_sub(t79, t40); + let t81 = circuit_add(t74, t78); // Fp2 add coeff 0/1 + let t82 = circuit_add(t75, t80); // Fp2 add coeff 1/1 + let t83 = circuit_add(in10, in14); // Fp2 add coeff 0/1 + let t84 = circuit_add(in11, in15); // Fp2 add coeff 1/1 + let t85 = circuit_add(in16, in20); // Fp2 add coeff 0/1 + let t86 = circuit_add(in17, in21); // Fp2 add coeff 1/1 + let t87 = circuit_mul(t85, t83); // Fp2 mul start + let t88 = circuit_mul(t86, t84); + let t89 = circuit_sub(t87, t88); // Fp2 mul real part end + let t90 = circuit_mul(t85, t84); + let t91 = circuit_mul(t86, t83); + let t92 = circuit_add(t90, t91); // Fp2 mul imag part end + let t93 = circuit_sub(t89, t25); // Fp2 sub coeff 0/1 + let t94 = circuit_sub(t92, t28); // Fp2 sub coeff 1/1 + let t95 = circuit_sub(t93, t37); // Fp2 sub coeff 0/1 + let t96 = circuit_sub(t94, t40); // Fp2 sub coeff 1/1 + let t97 = circuit_add(t95, t31); // Fp2 add coeff 0/1 + let t98 = circuit_add(t96, t34); // Fp2 add coeff 1/1 + let t99 = circuit_mul(t0, t17); // Fp2 mul start + let t100 = circuit_mul(t1, t18); + let t101 = circuit_sub(t99, t100); // Fp2 mul real part end + let t102 = circuit_mul(t0, t18); + let t103 = circuit_mul(t1, t17); + let t104 = circuit_add(t102, t103); // Fp2 mul imag part end + let t105 = circuit_mul(t2, t19); // Fp2 mul start + let t106 = circuit_mul(t3, t20); + let t107 = circuit_sub(t105, t106); // Fp2 mul real part end + let t108 = circuit_mul(t2, t20); + let t109 = circuit_mul(t3, t19); + let t110 = circuit_add(t108, t109); // Fp2 mul imag part end + let t111 = circuit_mul(t4, t21); // Fp2 mul start + let t112 = circuit_mul(t5, t22); + let t113 = circuit_sub(t111, t112); // Fp2 mul real part end + let t114 = circuit_mul(t4, t22); + let t115 = circuit_mul(t5, t21); + let t116 = circuit_add(t114, t115); // Fp2 mul imag part end + let t117 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t118 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t119 = circuit_add(t19, t21); // Fp2 add coeff 0/1 + let t120 = circuit_add(t20, t22); // Fp2 add coeff 1/1 + let t121 = circuit_mul(t117, t119); // Fp2 mul start + let t122 = circuit_mul(t118, t120); + let t123 = circuit_sub(t121, t122); // Fp2 mul real part end + let t124 = circuit_mul(t117, t120); + let t125 = circuit_mul(t118, t119); + let t126 = circuit_add(t124, t125); // Fp2 mul imag part end + let t127 = circuit_sub(t123, t107); // Fp2 sub coeff 0/1 + let t128 = circuit_sub(t126, t110); // Fp2 sub coeff 1/1 + let t129 = circuit_sub(t127, t113); // Fp2 sub coeff 0/1 + let t130 = circuit_sub(t128, t116); // Fp2 sub coeff 1/1 + let t131 = circuit_add(t129, t130); + let t132 = circuit_add(t131, t131); + let t133 = circuit_sub(t129, t130); + let t134 = circuit_sub(t132, t129); + let t135 = circuit_sub(t134, t130); + let t136 = circuit_add(t133, t101); // Fp2 add coeff 0/1 + let t137 = circuit_add(t135, t104); // Fp2 add coeff 1/1 + let t138 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t139 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t140 = circuit_add(t17, t19); // Fp2 add coeff 0/1 + let t141 = circuit_add(t18, t20); // Fp2 add coeff 1/1 + let t142 = circuit_mul(t138, t140); // Fp2 mul start + let t143 = circuit_mul(t139, t141); + let t144 = circuit_sub(t142, t143); // Fp2 mul real part end + let t145 = circuit_mul(t138, t141); + let t146 = circuit_mul(t139, t140); + let t147 = circuit_add(t145, t146); // Fp2 mul imag part end + let t148 = circuit_sub(t144, t101); // Fp2 sub coeff 0/1 + let t149 = circuit_sub(t147, t104); // Fp2 sub coeff 1/1 + let t150 = circuit_sub(t148, t107); // Fp2 sub coeff 0/1 + let t151 = circuit_sub(t149, t110); // Fp2 sub coeff 1/1 + let t152 = circuit_add(t113, t116); + let t153 = circuit_add(t152, t152); + let t154 = circuit_sub(t113, t116); + let t155 = circuit_sub(t153, t113); + let t156 = circuit_sub(t155, t116); + let t157 = circuit_add(t150, t154); // Fp2 add coeff 0/1 + let t158 = circuit_add(t151, t156); // Fp2 add coeff 1/1 + let t159 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t160 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t161 = circuit_add(t17, t21); // Fp2 add coeff 0/1 + let t162 = circuit_add(t18, t22); // Fp2 add coeff 1/1 + let t163 = circuit_mul(t161, t159); // Fp2 mul start + let t164 = circuit_mul(t162, t160); + let t165 = circuit_sub(t163, t164); // Fp2 mul real part end + let t166 = circuit_mul(t161, t160); + let t167 = circuit_mul(t162, t159); + let t168 = circuit_add(t166, t167); // Fp2 mul imag part end + let t169 = circuit_sub(t165, t101); // Fp2 sub coeff 0/1 + let t170 = circuit_sub(t168, t104); // Fp2 sub coeff 1/1 + let t171 = circuit_sub(t169, t113); // Fp2 sub coeff 0/1 + let t172 = circuit_sub(t170, t116); // Fp2 sub coeff 1/1 + let t173 = circuit_add(t171, t107); // Fp2 add coeff 0/1 + let t174 = circuit_add(t172, t110); // Fp2 add coeff 1/1 + let t175 = circuit_add(t136, t60); // Fp6 add coeff 0/5 + let t176 = circuit_add(t137, t61); // Fp6 add coeff 1/5 + let t177 = circuit_add(t157, t81); // Fp6 add coeff 2/5 + let t178 = circuit_add(t158, t82); // Fp6 add coeff 3/5 + let t179 = circuit_add(t173, t97); // Fp6 add coeff 4/5 + let t180 = circuit_add(t174, t98); // Fp6 add coeff 5/5 + let t181 = circuit_add(t60, t60); // Fp6 add coeff 0/5 + let t182 = circuit_add(t61, t61); // Fp6 add coeff 1/5 + let t183 = circuit_add(t81, t81); // Fp6 add coeff 2/5 + let t184 = circuit_add(t82, t82); // Fp6 add coeff 3/5 + let t185 = circuit_add(t97, t97); // Fp6 add coeff 4/5 + let t186 = circuit_add(t98, t98); // Fp6 add coeff 5/5 + let t187 = circuit_add(t97, t98); + let t188 = circuit_add(t187, t187); + let t189 = circuit_sub(t97, t98); + let t190 = circuit_sub(t188, t97); + let t191 = circuit_sub(t190, t98); + let t192 = circuit_add(t175, t189); // Fp6 add coeff 0/5 + let t193 = circuit_add(t176, t191); // Fp6 add coeff 1/5 + let t194 = circuit_add(t177, t60); // Fp6 add coeff 2/5 + let t195 = circuit_add(t178, t61); // Fp6 add coeff 3/5 + let t196 = circuit_add(t179, t81); // Fp6 add coeff 4/5 + let t197 = circuit_add(t180, t82); // Fp6 add coeff 5/5 + let t198 = circuit_add(in6, in7); // Doubling slope numerator start + let t199 = circuit_sub(in6, in7); + let t200 = circuit_mul(t198, t199); + let t201 = circuit_mul(in6, in7); + let t202 = circuit_mul(t200, in1); + let t203 = circuit_mul(t201, in2); // Doubling slope numerator end + let t204 = circuit_add(in8, in8); // Fp2 add coeff 0/1 + let t205 = circuit_add(in9, in9); // Fp2 add coeff 1/1 + let t206 = circuit_mul(t204, t204); // Fp2 Inv start + let t207 = circuit_mul(t205, t205); + let t208 = circuit_add(t206, t207); + let t209 = circuit_inverse(t208); + let t210 = circuit_mul(t204, t209); // Fp2 Inv real part end + let t211 = circuit_mul(t205, t209); + let t212 = circuit_sub(in0, t211); // Fp2 Inv imag part end + let t213 = circuit_mul(t202, t210); // Fp2 mul start + let t214 = circuit_mul(t203, t212); + let t215 = circuit_sub(t213, t214); // Fp2 mul real part end + let t216 = circuit_mul(t202, t212); + let t217 = circuit_mul(t203, t210); + let t218 = circuit_add(t216, t217); // Fp2 mul imag part end + let t219 = circuit_add(t215, t218); + let t220 = circuit_sub(t215, t218); + let t221 = circuit_mul(t219, t220); + let t222 = circuit_mul(t215, t218); + let t223 = circuit_add(t222, t222); + let t224 = circuit_add(in6, in6); // Fp2 add coeff 0/1 + let t225 = circuit_add(in7, in7); // Fp2 add coeff 1/1 + let t226 = circuit_sub(t221, t224); // Fp2 sub coeff 0/1 + let t227 = circuit_sub(t223, t225); // Fp2 sub coeff 1/1 + let t228 = circuit_sub(in6, t226); // Fp2 sub coeff 0/1 + let t229 = circuit_sub(in7, t227); // Fp2 sub coeff 1/1 + let t230 = circuit_mul(t215, t228); // Fp2 mul start + let t231 = circuit_mul(t218, t229); + let t232 = circuit_sub(t230, t231); // Fp2 mul real part end + let t233 = circuit_mul(t215, t229); + let t234 = circuit_mul(t218, t228); + let t235 = circuit_add(t233, t234); // Fp2 mul imag part end + let t236 = circuit_sub(t232, in8); // Fp2 sub coeff 0/1 + let t237 = circuit_sub(t235, in9); // Fp2 sub coeff 1/1 + let t238 = circuit_mul(t215, in6); // Fp2 mul start + let t239 = circuit_mul(t218, in7); + let t240 = circuit_sub(t238, t239); // Fp2 mul real part end + let t241 = circuit_mul(t215, in7); + let t242 = circuit_mul(t218, in6); + let t243 = circuit_add(t241, t242); // Fp2 mul imag part end + let t244 = circuit_sub(t240, in8); // Fp2 sub coeff 0/1 + let t245 = circuit_sub(t243, in9); // Fp2 sub coeff 1/1 + let t246 = circuit_mul(t244, in4); + let t247 = circuit_mul(t245, in4); + let t248 = circuit_mul(t215, in5); + let t249 = circuit_mul(t218, in5); + let t250 = circuit_mul(t192, t246); // Fp2 mul start + let t251 = circuit_mul(t193, t247); + let t252 = circuit_sub(t250, t251); // Fp2 mul real part end + let t253 = circuit_mul(t192, t247); + let t254 = circuit_mul(t193, t246); + let t255 = circuit_add(t253, t254); // Fp2 mul imag part end + let t256 = circuit_mul(t194, t248); // Fp2 mul start + let t257 = circuit_mul(t195, t249); + let t258 = circuit_sub(t256, t257); // Fp2 mul real part end + let t259 = circuit_mul(t194, t249); + let t260 = circuit_mul(t195, t248); + let t261 = circuit_add(t259, t260); // Fp2 mul imag part end + let t262 = circuit_add(t194, t196); // Fp2 add coeff 0/1 + let t263 = circuit_add(t195, t197); // Fp2 add coeff 1/1 + let t264 = circuit_mul(t248, t262); // Fp2 mul start + let t265 = circuit_mul(t249, t263); + let t266 = circuit_sub(t264, t265); // Fp2 mul real part end + let t267 = circuit_mul(t248, t263); + let t268 = circuit_mul(t249, t262); + let t269 = circuit_add(t267, t268); // Fp2 mul imag part end + let t270 = circuit_sub(t266, t258); // Fp2 sub coeff 0/1 + let t271 = circuit_sub(t269, t261); // Fp2 sub coeff 1/1 + let t272 = circuit_add(t270, t271); + let t273 = circuit_add(t272, t272); + let t274 = circuit_sub(t270, t271); + let t275 = circuit_sub(t273, t270); + let t276 = circuit_sub(t275, t271); + let t277 = circuit_add(t274, t252); // Fp2 add coeff 0/1 + let t278 = circuit_add(t276, t255); // Fp2 add coeff 1/1 + let t279 = circuit_add(t192, t196); // Fp2 add coeff 0/1 + let t280 = circuit_add(t193, t197); // Fp2 add coeff 1/1 + let t281 = circuit_mul(t246, t279); // Fp2 mul start + let t282 = circuit_mul(t247, t280); + let t283 = circuit_sub(t281, t282); // Fp2 mul real part end + let t284 = circuit_mul(t246, t280); + let t285 = circuit_mul(t247, t279); + let t286 = circuit_add(t284, t285); // Fp2 mul imag part end + let t287 = circuit_sub(t283, t252); // Fp2 sub coeff 0/1 + let t288 = circuit_sub(t286, t255); // Fp2 sub coeff 1/1 + let t289 = circuit_add(t287, t258); // Fp2 add coeff 0/1 + let t290 = circuit_add(t288, t261); // Fp2 add coeff 1/1 + let t291 = circuit_add(t246, t248); // Fp2 add coeff 0/1 + let t292 = circuit_add(t247, t249); // Fp2 add coeff 1/1 + let t293 = circuit_add(t192, t194); // Fp2 add coeff 0/1 + let t294 = circuit_add(t193, t195); // Fp2 add coeff 1/1 + let t295 = circuit_mul(t291, t293); // Fp2 mul start + let t296 = circuit_mul(t292, t294); + let t297 = circuit_sub(t295, t296); // Fp2 mul real part end + let t298 = circuit_mul(t291, t294); + let t299 = circuit_mul(t292, t293); + let t300 = circuit_add(t298, t299); // Fp2 mul imag part end + let t301 = circuit_sub(t297, t252); // Fp2 sub coeff 0/1 + let t302 = circuit_sub(t300, t255); // Fp2 sub coeff 1/1 + let t303 = circuit_sub(t301, t258); // Fp2 sub coeff 0/1 + let t304 = circuit_sub(t302, t261); // Fp2 sub coeff 1/1 + let t305 = circuit_add(t185, t186); + let t306 = circuit_add(t305, t305); + let t307 = circuit_sub(t185, t186); + let t308 = circuit_sub(t306, t185); + let t309 = circuit_sub(t308, t186); + let t310 = circuit_add(in3, t248); + let t311 = circuit_add(t181, t192); // Fp6 add coeff 0/5 + let t312 = circuit_add(t182, t193); // Fp6 add coeff 1/5 + let t313 = circuit_add(t183, t194); // Fp6 add coeff 2/5 + let t314 = circuit_add(t184, t195); // Fp6 add coeff 3/5 + let t315 = circuit_add(t185, t196); // Fp6 add coeff 4/5 + let t316 = circuit_add(t186, t197); // Fp6 add coeff 5/5 + let t317 = circuit_mul(t311, t246); // Fp2 mul start + let t318 = circuit_mul(t312, t247); + let t319 = circuit_sub(t317, t318); // Fp2 mul real part end + let t320 = circuit_mul(t311, t247); + let t321 = circuit_mul(t312, t246); + let t322 = circuit_add(t320, t321); // Fp2 mul imag part end + let t323 = circuit_mul(t313, t310); // Fp2 mul start + let t324 = circuit_mul(t314, t249); + let t325 = circuit_sub(t323, t324); // Fp2 mul real part end + let t326 = circuit_mul(t313, t249); + let t327 = circuit_mul(t314, t310); + let t328 = circuit_add(t326, t327); // Fp2 mul imag part end + let t329 = circuit_add(t313, t315); // Fp2 add coeff 0/1 + let t330 = circuit_add(t314, t316); // Fp2 add coeff 1/1 + let t331 = circuit_mul(t310, t329); // Fp2 mul start + let t332 = circuit_mul(t249, t330); + let t333 = circuit_sub(t331, t332); // Fp2 mul real part end + let t334 = circuit_mul(t310, t330); + let t335 = circuit_mul(t249, t329); + let t336 = circuit_add(t334, t335); // Fp2 mul imag part end + let t337 = circuit_sub(t333, t325); // Fp2 sub coeff 0/1 + let t338 = circuit_sub(t336, t328); // Fp2 sub coeff 1/1 + let t339 = circuit_add(t337, t338); + let t340 = circuit_add(t339, t339); + let t341 = circuit_sub(t337, t338); + let t342 = circuit_sub(t340, t337); + let t343 = circuit_sub(t342, t338); + let t344 = circuit_add(t341, t319); // Fp2 add coeff 0/1 + let t345 = circuit_add(t343, t322); // Fp2 add coeff 1/1 + let t346 = circuit_add(t311, t315); // Fp2 add coeff 0/1 + let t347 = circuit_add(t312, t316); // Fp2 add coeff 1/1 + let t348 = circuit_mul(t246, t346); // Fp2 mul start + let t349 = circuit_mul(t247, t347); + let t350 = circuit_sub(t348, t349); // Fp2 mul real part end + let t351 = circuit_mul(t246, t347); + let t352 = circuit_mul(t247, t346); + let t353 = circuit_add(t351, t352); // Fp2 mul imag part end + let t354 = circuit_sub(t350, t319); // Fp2 sub coeff 0/1 + let t355 = circuit_sub(t353, t322); // Fp2 sub coeff 1/1 + let t356 = circuit_add(t354, t325); // Fp2 add coeff 0/1 + let t357 = circuit_add(t355, t328); // Fp2 add coeff 1/1 + let t358 = circuit_add(t246, t310); // Fp2 add coeff 0/1 + let t359 = circuit_add(t247, t249); // Fp2 add coeff 1/1 + let t360 = circuit_add(t311, t313); // Fp2 add coeff 0/1 + let t361 = circuit_add(t312, t314); // Fp2 add coeff 1/1 + let t362 = circuit_mul(t358, t360); // Fp2 mul start + let t363 = circuit_mul(t359, t361); + let t364 = circuit_sub(t362, t363); // Fp2 mul real part end + let t365 = circuit_mul(t358, t361); + let t366 = circuit_mul(t359, t360); + let t367 = circuit_add(t365, t366); // Fp2 mul imag part end + let t368 = circuit_sub(t364, t319); // Fp2 sub coeff 0/1 + let t369 = circuit_sub(t367, t322); // Fp2 sub coeff 1/1 + let t370 = circuit_sub(t368, t325); // Fp2 sub coeff 0/1 + let t371 = circuit_sub(t369, t328); // Fp2 sub coeff 1/1 + let t372 = circuit_sub(t344, t277); // Fp6 sub coeff 0/5 + let t373 = circuit_sub(t345, t278); // Fp6 sub coeff 1/5 + let t374 = circuit_sub(t370, t303); // Fp6 sub coeff 2/5 + let t375 = circuit_sub(t371, t304); // Fp6 sub coeff 3/5 + let t376 = circuit_sub(t356, t289); // Fp6 sub coeff 4/5 + let t377 = circuit_sub(t357, t290); // Fp6 sub coeff 5/5 + let t378 = circuit_sub(t372, t307); // Fp6 sub coeff 0/5 + let t379 = circuit_sub(t373, t309); // Fp6 sub coeff 1/5 + let t380 = circuit_sub(t374, t181); // Fp6 sub coeff 2/5 + let t381 = circuit_sub(t375, t182); // Fp6 sub coeff 3/5 + let t382 = circuit_sub(t376, t183); // Fp6 sub coeff 4/5 + let t383 = circuit_sub(t377, t184); // Fp6 sub coeff 5/5 + let t384 = circuit_add(t183, t184); + let t385 = circuit_add(t384, t384); + let t386 = circuit_sub(t183, t184); + let t387 = circuit_sub(t385, t183); + let t388 = circuit_sub(t387, t184); + let t389 = circuit_add(t386, t277); // Fp6 add coeff 0/5 + let t390 = circuit_add(t388, t278); // Fp6 add coeff 1/5 + let t391 = circuit_add(t307, t303); // Fp6 add coeff 2/5 + let t392 = circuit_add(t309, t304); // Fp6 add coeff 3/5 + let t393 = circuit_add(t181, t289); // Fp6 add coeff 4/5 + let t394 = circuit_add(t182, t290); // Fp6 add coeff 5/5 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = ( + t226, + t227, + t236, + t237, + t389, + t390, + t391, + t392, + t393, + t394, + t378, + t379, + t380, + t381, + t382, + t383, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x3, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs.next_2([0x6, 0x0, 0x0, 0x0]); // in2 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in3 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(yInv_0); // in4 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in5 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in6 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in7 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in8 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in9 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a0); // in10 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a1); // in11 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a0); // in12 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a1); // in13 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a0); // in14 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a1); // in15 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a0); // in16 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a1); // in17 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a0); // in18 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a1); // in19 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a0); // in20 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a1); // in21 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Q0: G2Point = G2Point { + x0: outputs.get_output(t226), + x1: outputs.get_output(t227), + y0: outputs.get_output(t236), + y1: outputs.get_output(t237) + }; + let Mi_plus_one: E12T = E12T { + c0b0a0: outputs.get_output(t389), + c0b0a1: outputs.get_output(t390), + c0b1a0: outputs.get_output(t391), + c0b1a1: outputs.get_output(t392), + c0b2a0: outputs.get_output(t393), + c0b2a1: outputs.get_output(t394), + c1b0a0: outputs.get_output(t378), + c1b0a1: outputs.get_output(t379), + c1b1a0: outputs.get_output(t380), + c1b1a1: outputs.get_output(t381), + c1b2a0: outputs.get_output(t382), + c1b2a1: outputs.get_output(t383), + }; + return (Q0, Mi_plus_one); +} +#[inline(always)] +fn run_BLS12_381_TOWER_MILLER_BIT1_1P_circuit( + yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point, Q_or_Q_neg_0: G2Point, M_i: E12T +) -> (G2Point, E12T) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x1 + + // INPUT stack + let (in2, in3, in4) = (CE::> {}, CE::> {}, CE::> {}); + let (in5, in6, in7) = (CE::> {}, CE::> {}, CE::> {}); + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let (in17, in18, in19) = (CE::> {}, CE::> {}, CE::> {}); + let (in20, in21, in22) = (CE::> {}, CE::> {}, CE::> {}); + let in23 = CE::> {}; + let t0 = circuit_sub(in12, in18); // Fp6 sub coeff 0/5 + let t1 = circuit_sub(in13, in19); // Fp6 sub coeff 1/5 + let t2 = circuit_sub(in14, in20); // Fp6 sub coeff 2/5 + let t3 = circuit_sub(in15, in21); // Fp6 sub coeff 3/5 + let t4 = circuit_sub(in16, in22); // Fp6 sub coeff 4/5 + let t5 = circuit_sub(in17, in23); // Fp6 sub coeff 5/5 + let t6 = circuit_add(in22, in23); + let t7 = circuit_add(t6, t6); + let t8 = circuit_sub(in22, in23); + let t9 = circuit_sub(t7, in22); + let t10 = circuit_sub(t9, in23); + let t11 = circuit_sub(in0, t8); // Fp6 neg coeff 0/5 + let t12 = circuit_sub(in0, t10); // Fp6 neg coeff 1/5 + let t13 = circuit_sub(in0, in18); // Fp6 neg coeff 2/5 + let t14 = circuit_sub(in0, in19); // Fp6 neg coeff 3/5 + let t15 = circuit_sub(in0, in20); // Fp6 neg coeff 4/5 + let t16 = circuit_sub(in0, in21); // Fp6 neg coeff 5/5 + let t17 = circuit_add(in12, t11); // Fp6 add coeff 0/5 + let t18 = circuit_add(in13, t12); // Fp6 add coeff 1/5 + let t19 = circuit_add(in14, t13); // Fp6 add coeff 2/5 + let t20 = circuit_add(in15, t14); // Fp6 add coeff 3/5 + let t21 = circuit_add(in16, t15); // Fp6 add coeff 4/5 + let t22 = circuit_add(in17, t16); // Fp6 add coeff 5/5 + let t23 = circuit_mul(in12, in18); // Fp2 mul start + let t24 = circuit_mul(in13, in19); + let t25 = circuit_sub(t23, t24); // Fp2 mul real part end + let t26 = circuit_mul(in12, in19); + let t27 = circuit_mul(in13, in18); + let t28 = circuit_add(t26, t27); // Fp2 mul imag part end + let t29 = circuit_mul(in14, in20); // Fp2 mul start + let t30 = circuit_mul(in15, in21); + let t31 = circuit_sub(t29, t30); // Fp2 mul real part end + let t32 = circuit_mul(in14, in21); + let t33 = circuit_mul(in15, in20); + let t34 = circuit_add(t32, t33); // Fp2 mul imag part end + let t35 = circuit_mul(in16, in22); // Fp2 mul start + let t36 = circuit_mul(in17, in23); + let t37 = circuit_sub(t35, t36); // Fp2 mul real part end + let t38 = circuit_mul(in16, in23); + let t39 = circuit_mul(in17, in22); + let t40 = circuit_add(t38, t39); // Fp2 mul imag part end + let t41 = circuit_add(in14, in16); // Fp2 add coeff 0/1 + let t42 = circuit_add(in15, in17); // Fp2 add coeff 1/1 + let t43 = circuit_add(in20, in22); // Fp2 add coeff 0/1 + let t44 = circuit_add(in21, in23); // Fp2 add coeff 1/1 + let t45 = circuit_mul(t41, t43); // Fp2 mul start + let t46 = circuit_mul(t42, t44); + let t47 = circuit_sub(t45, t46); // Fp2 mul real part end + let t48 = circuit_mul(t41, t44); + let t49 = circuit_mul(t42, t43); + let t50 = circuit_add(t48, t49); // Fp2 mul imag part end + let t51 = circuit_sub(t47, t31); // Fp2 sub coeff 0/1 + let t52 = circuit_sub(t50, t34); // Fp2 sub coeff 1/1 + let t53 = circuit_sub(t51, t37); // Fp2 sub coeff 0/1 + let t54 = circuit_sub(t52, t40); // Fp2 sub coeff 1/1 + let t55 = circuit_add(t53, t54); + let t56 = circuit_add(t55, t55); + let t57 = circuit_sub(t53, t54); + let t58 = circuit_sub(t56, t53); + let t59 = circuit_sub(t58, t54); + let t60 = circuit_add(t57, t25); // Fp2 add coeff 0/1 + let t61 = circuit_add(t59, t28); // Fp2 add coeff 1/1 + let t62 = circuit_add(in12, in14); // Fp2 add coeff 0/1 + let t63 = circuit_add(in13, in15); // Fp2 add coeff 1/1 + let t64 = circuit_add(in18, in20); // Fp2 add coeff 0/1 + let t65 = circuit_add(in19, in21); // Fp2 add coeff 1/1 + let t66 = circuit_mul(t62, t64); // Fp2 mul start + let t67 = circuit_mul(t63, t65); + let t68 = circuit_sub(t66, t67); // Fp2 mul real part end + let t69 = circuit_mul(t62, t65); + let t70 = circuit_mul(t63, t64); + let t71 = circuit_add(t69, t70); // Fp2 mul imag part end + let t72 = circuit_sub(t68, t25); // Fp2 sub coeff 0/1 + let t73 = circuit_sub(t71, t28); // Fp2 sub coeff 1/1 + let t74 = circuit_sub(t72, t31); // Fp2 sub coeff 0/1 + let t75 = circuit_sub(t73, t34); // Fp2 sub coeff 1/1 + let t76 = circuit_add(t37, t40); + let t77 = circuit_add(t76, t76); + let t78 = circuit_sub(t37, t40); + let t79 = circuit_sub(t77, t37); + let t80 = circuit_sub(t79, t40); + let t81 = circuit_add(t74, t78); // Fp2 add coeff 0/1 + let t82 = circuit_add(t75, t80); // Fp2 add coeff 1/1 + let t83 = circuit_add(in12, in16); // Fp2 add coeff 0/1 + let t84 = circuit_add(in13, in17); // Fp2 add coeff 1/1 + let t85 = circuit_add(in18, in22); // Fp2 add coeff 0/1 + let t86 = circuit_add(in19, in23); // Fp2 add coeff 1/1 + let t87 = circuit_mul(t85, t83); // Fp2 mul start + let t88 = circuit_mul(t86, t84); + let t89 = circuit_sub(t87, t88); // Fp2 mul real part end + let t90 = circuit_mul(t85, t84); + let t91 = circuit_mul(t86, t83); + let t92 = circuit_add(t90, t91); // Fp2 mul imag part end + let t93 = circuit_sub(t89, t25); // Fp2 sub coeff 0/1 + let t94 = circuit_sub(t92, t28); // Fp2 sub coeff 1/1 + let t95 = circuit_sub(t93, t37); // Fp2 sub coeff 0/1 + let t96 = circuit_sub(t94, t40); // Fp2 sub coeff 1/1 + let t97 = circuit_add(t95, t31); // Fp2 add coeff 0/1 + let t98 = circuit_add(t96, t34); // Fp2 add coeff 1/1 + let t99 = circuit_mul(t0, t17); // Fp2 mul start + let t100 = circuit_mul(t1, t18); + let t101 = circuit_sub(t99, t100); // Fp2 mul real part end + let t102 = circuit_mul(t0, t18); + let t103 = circuit_mul(t1, t17); + let t104 = circuit_add(t102, t103); // Fp2 mul imag part end + let t105 = circuit_mul(t2, t19); // Fp2 mul start + let t106 = circuit_mul(t3, t20); + let t107 = circuit_sub(t105, t106); // Fp2 mul real part end + let t108 = circuit_mul(t2, t20); + let t109 = circuit_mul(t3, t19); + let t110 = circuit_add(t108, t109); // Fp2 mul imag part end + let t111 = circuit_mul(t4, t21); // Fp2 mul start + let t112 = circuit_mul(t5, t22); + let t113 = circuit_sub(t111, t112); // Fp2 mul real part end + let t114 = circuit_mul(t4, t22); + let t115 = circuit_mul(t5, t21); + let t116 = circuit_add(t114, t115); // Fp2 mul imag part end + let t117 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t118 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t119 = circuit_add(t19, t21); // Fp2 add coeff 0/1 + let t120 = circuit_add(t20, t22); // Fp2 add coeff 1/1 + let t121 = circuit_mul(t117, t119); // Fp2 mul start + let t122 = circuit_mul(t118, t120); + let t123 = circuit_sub(t121, t122); // Fp2 mul real part end + let t124 = circuit_mul(t117, t120); + let t125 = circuit_mul(t118, t119); + let t126 = circuit_add(t124, t125); // Fp2 mul imag part end + let t127 = circuit_sub(t123, t107); // Fp2 sub coeff 0/1 + let t128 = circuit_sub(t126, t110); // Fp2 sub coeff 1/1 + let t129 = circuit_sub(t127, t113); // Fp2 sub coeff 0/1 + let t130 = circuit_sub(t128, t116); // Fp2 sub coeff 1/1 + let t131 = circuit_add(t129, t130); + let t132 = circuit_add(t131, t131); + let t133 = circuit_sub(t129, t130); + let t134 = circuit_sub(t132, t129); + let t135 = circuit_sub(t134, t130); + let t136 = circuit_add(t133, t101); // Fp2 add coeff 0/1 + let t137 = circuit_add(t135, t104); // Fp2 add coeff 1/1 + let t138 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t139 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t140 = circuit_add(t17, t19); // Fp2 add coeff 0/1 + let t141 = circuit_add(t18, t20); // Fp2 add coeff 1/1 + let t142 = circuit_mul(t138, t140); // Fp2 mul start + let t143 = circuit_mul(t139, t141); + let t144 = circuit_sub(t142, t143); // Fp2 mul real part end + let t145 = circuit_mul(t138, t141); + let t146 = circuit_mul(t139, t140); + let t147 = circuit_add(t145, t146); // Fp2 mul imag part end + let t148 = circuit_sub(t144, t101); // Fp2 sub coeff 0/1 + let t149 = circuit_sub(t147, t104); // Fp2 sub coeff 1/1 + let t150 = circuit_sub(t148, t107); // Fp2 sub coeff 0/1 + let t151 = circuit_sub(t149, t110); // Fp2 sub coeff 1/1 + let t152 = circuit_add(t113, t116); + let t153 = circuit_add(t152, t152); + let t154 = circuit_sub(t113, t116); + let t155 = circuit_sub(t153, t113); + let t156 = circuit_sub(t155, t116); + let t157 = circuit_add(t150, t154); // Fp2 add coeff 0/1 + let t158 = circuit_add(t151, t156); // Fp2 add coeff 1/1 + let t159 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t160 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t161 = circuit_add(t17, t21); // Fp2 add coeff 0/1 + let t162 = circuit_add(t18, t22); // Fp2 add coeff 1/1 + let t163 = circuit_mul(t161, t159); // Fp2 mul start + let t164 = circuit_mul(t162, t160); + let t165 = circuit_sub(t163, t164); // Fp2 mul real part end + let t166 = circuit_mul(t161, t160); + let t167 = circuit_mul(t162, t159); + let t168 = circuit_add(t166, t167); // Fp2 mul imag part end + let t169 = circuit_sub(t165, t101); // Fp2 sub coeff 0/1 + let t170 = circuit_sub(t168, t104); // Fp2 sub coeff 1/1 + let t171 = circuit_sub(t169, t113); // Fp2 sub coeff 0/1 + let t172 = circuit_sub(t170, t116); // Fp2 sub coeff 1/1 + let t173 = circuit_add(t171, t107); // Fp2 add coeff 0/1 + let t174 = circuit_add(t172, t110); // Fp2 add coeff 1/1 + let t175 = circuit_add(t136, t60); // Fp6 add coeff 0/5 + let t176 = circuit_add(t137, t61); // Fp6 add coeff 1/5 + let t177 = circuit_add(t157, t81); // Fp6 add coeff 2/5 + let t178 = circuit_add(t158, t82); // Fp6 add coeff 3/5 + let t179 = circuit_add(t173, t97); // Fp6 add coeff 4/5 + let t180 = circuit_add(t174, t98); // Fp6 add coeff 5/5 + let t181 = circuit_add(t60, t60); // Fp6 add coeff 0/5 + let t182 = circuit_add(t61, t61); // Fp6 add coeff 1/5 + let t183 = circuit_add(t81, t81); // Fp6 add coeff 2/5 + let t184 = circuit_add(t82, t82); // Fp6 add coeff 3/5 + let t185 = circuit_add(t97, t97); // Fp6 add coeff 4/5 + let t186 = circuit_add(t98, t98); // Fp6 add coeff 5/5 + let t187 = circuit_add(t97, t98); + let t188 = circuit_add(t187, t187); + let t189 = circuit_sub(t97, t98); + let t190 = circuit_sub(t188, t97); + let t191 = circuit_sub(t190, t98); + let t192 = circuit_add(t175, t189); // Fp6 add coeff 0/5 + let t193 = circuit_add(t176, t191); // Fp6 add coeff 1/5 + let t194 = circuit_add(t177, t60); // Fp6 add coeff 2/5 + let t195 = circuit_add(t178, t61); // Fp6 add coeff 3/5 + let t196 = circuit_add(t179, t81); // Fp6 add coeff 4/5 + let t197 = circuit_add(t180, t82); // Fp6 add coeff 5/5 + let t198 = circuit_sub(in6, in10); // Fp2 sub coeff 0/1 + let t199 = circuit_sub(in7, in11); // Fp2 sub coeff 1/1 + let t200 = circuit_sub(in4, in8); // Fp2 sub coeff 0/1 + let t201 = circuit_sub(in5, in9); // Fp2 sub coeff 1/1 + let t202 = circuit_mul(t200, t200); // Fp2 Inv start + let t203 = circuit_mul(t201, t201); + let t204 = circuit_add(t202, t203); + let t205 = circuit_inverse(t204); + let t206 = circuit_mul(t200, t205); // Fp2 Inv real part end + let t207 = circuit_mul(t201, t205); + let t208 = circuit_sub(in0, t207); // Fp2 Inv imag part end + let t209 = circuit_mul(t198, t206); // Fp2 mul start + let t210 = circuit_mul(t199, t208); + let t211 = circuit_sub(t209, t210); // Fp2 mul real part end + let t212 = circuit_mul(t198, t208); + let t213 = circuit_mul(t199, t206); + let t214 = circuit_add(t212, t213); // Fp2 mul imag part end + let t215 = circuit_add(t211, t214); + let t216 = circuit_sub(t211, t214); + let t217 = circuit_mul(t215, t216); + let t218 = circuit_mul(t211, t214); + let t219 = circuit_add(t218, t218); + let t220 = circuit_add(in4, in8); // Fp2 add coeff 0/1 + let t221 = circuit_add(in5, in9); // Fp2 add coeff 1/1 + let t222 = circuit_sub(t217, t220); // Fp2 sub coeff 0/1 + let t223 = circuit_sub(t219, t221); // Fp2 sub coeff 1/1 + let t224 = circuit_mul(t211, in4); // Fp2 mul start + let t225 = circuit_mul(t214, in5); + let t226 = circuit_sub(t224, t225); // Fp2 mul real part end + let t227 = circuit_mul(t211, in5); + let t228 = circuit_mul(t214, in4); + let t229 = circuit_add(t227, t228); // Fp2 mul imag part end + let t230 = circuit_sub(t226, in6); // Fp2 sub coeff 0/1 + let t231 = circuit_sub(t229, in7); // Fp2 sub coeff 1/1 + let t232 = circuit_add(in6, in6); // Fp2 add coeff 0/1 + let t233 = circuit_add(in7, in7); // Fp2 add coeff 1/1 + let t234 = circuit_sub(t222, in4); // Fp2 sub coeff 0/1 + let t235 = circuit_sub(t223, in5); // Fp2 sub coeff 1/1 + let t236 = circuit_mul(t234, t234); // Fp2 Inv start + let t237 = circuit_mul(t235, t235); + let t238 = circuit_add(t236, t237); + let t239 = circuit_inverse(t238); + let t240 = circuit_mul(t234, t239); // Fp2 Inv real part end + let t241 = circuit_mul(t235, t239); + let t242 = circuit_sub(in0, t241); // Fp2 Inv imag part end + let t243 = circuit_mul(t232, t240); // Fp2 mul start + let t244 = circuit_mul(t233, t242); + let t245 = circuit_sub(t243, t244); // Fp2 mul real part end + let t246 = circuit_mul(t232, t242); + let t247 = circuit_mul(t233, t240); + let t248 = circuit_add(t246, t247); // Fp2 mul imag part end + let t249 = circuit_add(t211, t245); // Fp2 add coeff 0/1 + let t250 = circuit_add(t214, t248); // Fp2 add coeff 1/1 + let t251 = circuit_sub(in0, t249); // Fp2 neg coeff 0/1 + let t252 = circuit_sub(in0, t250); // Fp2 neg coeff 1/1 + let t253 = circuit_add(t251, t252); + let t254 = circuit_sub(t251, t252); + let t255 = circuit_mul(t253, t254); + let t256 = circuit_mul(t251, t252); + let t257 = circuit_add(t256, t256); + let t258 = circuit_sub(t255, in4); // Fp2 sub coeff 0/1 + let t259 = circuit_sub(t257, in5); // Fp2 sub coeff 1/1 + let t260 = circuit_sub(t258, t222); // Fp2 sub coeff 0/1 + let t261 = circuit_sub(t259, t223); // Fp2 sub coeff 1/1 + let t262 = circuit_sub(in4, t260); // Fp2 sub coeff 0/1 + let t263 = circuit_sub(in5, t261); // Fp2 sub coeff 1/1 + let t264 = circuit_mul(t251, t262); // Fp2 mul start + let t265 = circuit_mul(t252, t263); + let t266 = circuit_sub(t264, t265); // Fp2 mul real part end + let t267 = circuit_mul(t251, t263); + let t268 = circuit_mul(t252, t262); + let t269 = circuit_add(t267, t268); // Fp2 mul imag part end + let t270 = circuit_sub(t266, in6); // Fp2 sub coeff 0/1 + let t271 = circuit_sub(t269, in7); // Fp2 sub coeff 1/1 + let t272 = circuit_mul(t251, in4); // Fp2 mul start + let t273 = circuit_mul(t252, in5); + let t274 = circuit_sub(t272, t273); // Fp2 mul real part end + let t275 = circuit_mul(t251, in5); + let t276 = circuit_mul(t252, in4); + let t277 = circuit_add(t275, t276); // Fp2 mul imag part end + let t278 = circuit_sub(t274, in6); // Fp2 sub coeff 0/1 + let t279 = circuit_sub(t277, in7); // Fp2 sub coeff 1/1 + let t280 = circuit_mul(t230, in2); + let t281 = circuit_mul(t231, in2); + let t282 = circuit_mul(t211, in3); + let t283 = circuit_mul(t214, in3); + let t284 = circuit_mul(t278, in2); + let t285 = circuit_mul(t279, in2); + let t286 = circuit_mul(t251, in3); + let t287 = circuit_mul(t252, in3); + let t288 = circuit_mul(t192, t280); // Fp2 mul start + let t289 = circuit_mul(t193, t281); + let t290 = circuit_sub(t288, t289); // Fp2 mul real part end + let t291 = circuit_mul(t192, t281); + let t292 = circuit_mul(t193, t280); + let t293 = circuit_add(t291, t292); // Fp2 mul imag part end + let t294 = circuit_mul(t194, t282); // Fp2 mul start + let t295 = circuit_mul(t195, t283); + let t296 = circuit_sub(t294, t295); // Fp2 mul real part end + let t297 = circuit_mul(t194, t283); + let t298 = circuit_mul(t195, t282); + let t299 = circuit_add(t297, t298); // Fp2 mul imag part end + let t300 = circuit_add(t194, t196); // Fp2 add coeff 0/1 + let t301 = circuit_add(t195, t197); // Fp2 add coeff 1/1 + let t302 = circuit_mul(t282, t300); // Fp2 mul start + let t303 = circuit_mul(t283, t301); + let t304 = circuit_sub(t302, t303); // Fp2 mul real part end + let t305 = circuit_mul(t282, t301); + let t306 = circuit_mul(t283, t300); + let t307 = circuit_add(t305, t306); // Fp2 mul imag part end + let t308 = circuit_sub(t304, t296); // Fp2 sub coeff 0/1 + let t309 = circuit_sub(t307, t299); // Fp2 sub coeff 1/1 + let t310 = circuit_add(t308, t309); + let t311 = circuit_add(t310, t310); + let t312 = circuit_sub(t308, t309); + let t313 = circuit_sub(t311, t308); + let t314 = circuit_sub(t313, t309); + let t315 = circuit_add(t312, t290); // Fp2 add coeff 0/1 + let t316 = circuit_add(t314, t293); // Fp2 add coeff 1/1 + let t317 = circuit_add(t192, t196); // Fp2 add coeff 0/1 + let t318 = circuit_add(t193, t197); // Fp2 add coeff 1/1 + let t319 = circuit_mul(t280, t317); // Fp2 mul start + let t320 = circuit_mul(t281, t318); + let t321 = circuit_sub(t319, t320); // Fp2 mul real part end + let t322 = circuit_mul(t280, t318); + let t323 = circuit_mul(t281, t317); + let t324 = circuit_add(t322, t323); // Fp2 mul imag part end + let t325 = circuit_sub(t321, t290); // Fp2 sub coeff 0/1 + let t326 = circuit_sub(t324, t293); // Fp2 sub coeff 1/1 + let t327 = circuit_add(t325, t296); // Fp2 add coeff 0/1 + let t328 = circuit_add(t326, t299); // Fp2 add coeff 1/1 + let t329 = circuit_add(t280, t282); // Fp2 add coeff 0/1 + let t330 = circuit_add(t281, t283); // Fp2 add coeff 1/1 + let t331 = circuit_add(t192, t194); // Fp2 add coeff 0/1 + let t332 = circuit_add(t193, t195); // Fp2 add coeff 1/1 + let t333 = circuit_mul(t329, t331); // Fp2 mul start + let t334 = circuit_mul(t330, t332); + let t335 = circuit_sub(t333, t334); // Fp2 mul real part end + let t336 = circuit_mul(t329, t332); + let t337 = circuit_mul(t330, t331); + let t338 = circuit_add(t336, t337); // Fp2 mul imag part end + let t339 = circuit_sub(t335, t290); // Fp2 sub coeff 0/1 + let t340 = circuit_sub(t338, t293); // Fp2 sub coeff 1/1 + let t341 = circuit_sub(t339, t296); // Fp2 sub coeff 0/1 + let t342 = circuit_sub(t340, t299); // Fp2 sub coeff 1/1 + let t343 = circuit_add(t185, t186); + let t344 = circuit_add(t343, t343); + let t345 = circuit_sub(t185, t186); + let t346 = circuit_sub(t344, t185); + let t347 = circuit_sub(t346, t186); + let t348 = circuit_add(in1, t282); + let t349 = circuit_add(t181, t192); // Fp6 add coeff 0/5 + let t350 = circuit_add(t182, t193); // Fp6 add coeff 1/5 + let t351 = circuit_add(t183, t194); // Fp6 add coeff 2/5 + let t352 = circuit_add(t184, t195); // Fp6 add coeff 3/5 + let t353 = circuit_add(t185, t196); // Fp6 add coeff 4/5 + let t354 = circuit_add(t186, t197); // Fp6 add coeff 5/5 + let t355 = circuit_mul(t349, t280); // Fp2 mul start + let t356 = circuit_mul(t350, t281); + let t357 = circuit_sub(t355, t356); // Fp2 mul real part end + let t358 = circuit_mul(t349, t281); + let t359 = circuit_mul(t350, t280); + let t360 = circuit_add(t358, t359); // Fp2 mul imag part end + let t361 = circuit_mul(t351, t348); // Fp2 mul start + let t362 = circuit_mul(t352, t283); + let t363 = circuit_sub(t361, t362); // Fp2 mul real part end + let t364 = circuit_mul(t351, t283); + let t365 = circuit_mul(t352, t348); + let t366 = circuit_add(t364, t365); // Fp2 mul imag part end + let t367 = circuit_add(t351, t353); // Fp2 add coeff 0/1 + let t368 = circuit_add(t352, t354); // Fp2 add coeff 1/1 + let t369 = circuit_mul(t348, t367); // Fp2 mul start + let t370 = circuit_mul(t283, t368); + let t371 = circuit_sub(t369, t370); // Fp2 mul real part end + let t372 = circuit_mul(t348, t368); + let t373 = circuit_mul(t283, t367); + let t374 = circuit_add(t372, t373); // Fp2 mul imag part end + let t375 = circuit_sub(t371, t363); // Fp2 sub coeff 0/1 + let t376 = circuit_sub(t374, t366); // Fp2 sub coeff 1/1 + let t377 = circuit_add(t375, t376); + let t378 = circuit_add(t377, t377); + let t379 = circuit_sub(t375, t376); + let t380 = circuit_sub(t378, t375); + let t381 = circuit_sub(t380, t376); + let t382 = circuit_add(t379, t357); // Fp2 add coeff 0/1 + let t383 = circuit_add(t381, t360); // Fp2 add coeff 1/1 + let t384 = circuit_add(t349, t353); // Fp2 add coeff 0/1 + let t385 = circuit_add(t350, t354); // Fp2 add coeff 1/1 + let t386 = circuit_mul(t280, t384); // Fp2 mul start + let t387 = circuit_mul(t281, t385); + let t388 = circuit_sub(t386, t387); // Fp2 mul real part end + let t389 = circuit_mul(t280, t385); + let t390 = circuit_mul(t281, t384); + let t391 = circuit_add(t389, t390); // Fp2 mul imag part end + let t392 = circuit_sub(t388, t357); // Fp2 sub coeff 0/1 + let t393 = circuit_sub(t391, t360); // Fp2 sub coeff 1/1 + let t394 = circuit_add(t392, t363); // Fp2 add coeff 0/1 + let t395 = circuit_add(t393, t366); // Fp2 add coeff 1/1 + let t396 = circuit_add(t280, t348); // Fp2 add coeff 0/1 + let t397 = circuit_add(t281, t283); // Fp2 add coeff 1/1 + let t398 = circuit_add(t349, t351); // Fp2 add coeff 0/1 + let t399 = circuit_add(t350, t352); // Fp2 add coeff 1/1 + let t400 = circuit_mul(t396, t398); // Fp2 mul start + let t401 = circuit_mul(t397, t399); + let t402 = circuit_sub(t400, t401); // Fp2 mul real part end + let t403 = circuit_mul(t396, t399); + let t404 = circuit_mul(t397, t398); + let t405 = circuit_add(t403, t404); // Fp2 mul imag part end + let t406 = circuit_sub(t402, t357); // Fp2 sub coeff 0/1 + let t407 = circuit_sub(t405, t360); // Fp2 sub coeff 1/1 + let t408 = circuit_sub(t406, t363); // Fp2 sub coeff 0/1 + let t409 = circuit_sub(t407, t366); // Fp2 sub coeff 1/1 + let t410 = circuit_sub(t382, t315); // Fp6 sub coeff 0/5 + let t411 = circuit_sub(t383, t316); // Fp6 sub coeff 1/5 + let t412 = circuit_sub(t408, t341); // Fp6 sub coeff 2/5 + let t413 = circuit_sub(t409, t342); // Fp6 sub coeff 3/5 + let t414 = circuit_sub(t394, t327); // Fp6 sub coeff 4/5 + let t415 = circuit_sub(t395, t328); // Fp6 sub coeff 5/5 + let t416 = circuit_sub(t410, t345); // Fp6 sub coeff 0/5 + let t417 = circuit_sub(t411, t347); // Fp6 sub coeff 1/5 + let t418 = circuit_sub(t412, t181); // Fp6 sub coeff 2/5 + let t419 = circuit_sub(t413, t182); // Fp6 sub coeff 3/5 + let t420 = circuit_sub(t414, t183); // Fp6 sub coeff 4/5 + let t421 = circuit_sub(t415, t184); // Fp6 sub coeff 5/5 + let t422 = circuit_add(t183, t184); + let t423 = circuit_add(t422, t422); + let t424 = circuit_sub(t183, t184); + let t425 = circuit_sub(t423, t183); + let t426 = circuit_sub(t425, t184); + let t427 = circuit_add(t424, t315); // Fp6 add coeff 0/5 + let t428 = circuit_add(t426, t316); // Fp6 add coeff 1/5 + let t429 = circuit_add(t345, t341); // Fp6 add coeff 2/5 + let t430 = circuit_add(t347, t342); // Fp6 add coeff 3/5 + let t431 = circuit_add(t181, t327); // Fp6 add coeff 4/5 + let t432 = circuit_add(t182, t328); // Fp6 add coeff 5/5 + let t433 = circuit_mul(t427, t284); // Fp2 mul start + let t434 = circuit_mul(t428, t285); + let t435 = circuit_sub(t433, t434); // Fp2 mul real part end + let t436 = circuit_mul(t427, t285); + let t437 = circuit_mul(t428, t284); + let t438 = circuit_add(t436, t437); // Fp2 mul imag part end + let t439 = circuit_mul(t429, t286); // Fp2 mul start + let t440 = circuit_mul(t430, t287); + let t441 = circuit_sub(t439, t440); // Fp2 mul real part end + let t442 = circuit_mul(t429, t287); + let t443 = circuit_mul(t430, t286); + let t444 = circuit_add(t442, t443); // Fp2 mul imag part end + let t445 = circuit_add(t429, t431); // Fp2 add coeff 0/1 + let t446 = circuit_add(t430, t432); // Fp2 add coeff 1/1 + let t447 = circuit_mul(t286, t445); // Fp2 mul start + let t448 = circuit_mul(t287, t446); + let t449 = circuit_sub(t447, t448); // Fp2 mul real part end + let t450 = circuit_mul(t286, t446); + let t451 = circuit_mul(t287, t445); + let t452 = circuit_add(t450, t451); // Fp2 mul imag part end + let t453 = circuit_sub(t449, t441); // Fp2 sub coeff 0/1 + let t454 = circuit_sub(t452, t444); // Fp2 sub coeff 1/1 + let t455 = circuit_add(t453, t454); + let t456 = circuit_add(t455, t455); + let t457 = circuit_sub(t453, t454); + let t458 = circuit_sub(t456, t453); + let t459 = circuit_sub(t458, t454); + let t460 = circuit_add(t457, t435); // Fp2 add coeff 0/1 + let t461 = circuit_add(t459, t438); // Fp2 add coeff 1/1 + let t462 = circuit_add(t427, t431); // Fp2 add coeff 0/1 + let t463 = circuit_add(t428, t432); // Fp2 add coeff 1/1 + let t464 = circuit_mul(t284, t462); // Fp2 mul start + let t465 = circuit_mul(t285, t463); + let t466 = circuit_sub(t464, t465); // Fp2 mul real part end + let t467 = circuit_mul(t284, t463); + let t468 = circuit_mul(t285, t462); + let t469 = circuit_add(t467, t468); // Fp2 mul imag part end + let t470 = circuit_sub(t466, t435); // Fp2 sub coeff 0/1 + let t471 = circuit_sub(t469, t438); // Fp2 sub coeff 1/1 + let t472 = circuit_add(t470, t441); // Fp2 add coeff 0/1 + let t473 = circuit_add(t471, t444); // Fp2 add coeff 1/1 + let t474 = circuit_add(t284, t286); // Fp2 add coeff 0/1 + let t475 = circuit_add(t285, t287); // Fp2 add coeff 1/1 + let t476 = circuit_add(t427, t429); // Fp2 add coeff 0/1 + let t477 = circuit_add(t428, t430); // Fp2 add coeff 1/1 + let t478 = circuit_mul(t474, t476); // Fp2 mul start + let t479 = circuit_mul(t475, t477); + let t480 = circuit_sub(t478, t479); // Fp2 mul real part end + let t481 = circuit_mul(t474, t477); + let t482 = circuit_mul(t475, t476); + let t483 = circuit_add(t481, t482); // Fp2 mul imag part end + let t484 = circuit_sub(t480, t435); // Fp2 sub coeff 0/1 + let t485 = circuit_sub(t483, t438); // Fp2 sub coeff 1/1 + let t486 = circuit_sub(t484, t441); // Fp2 sub coeff 0/1 + let t487 = circuit_sub(t485, t444); // Fp2 sub coeff 1/1 + let t488 = circuit_add(t420, t421); + let t489 = circuit_add(t488, t488); + let t490 = circuit_sub(t420, t421); + let t491 = circuit_sub(t489, t420); + let t492 = circuit_sub(t491, t421); + let t493 = circuit_add(in1, t286); + let t494 = circuit_add(t416, t427); // Fp6 add coeff 0/5 + let t495 = circuit_add(t417, t428); // Fp6 add coeff 1/5 + let t496 = circuit_add(t418, t429); // Fp6 add coeff 2/5 + let t497 = circuit_add(t419, t430); // Fp6 add coeff 3/5 + let t498 = circuit_add(t420, t431); // Fp6 add coeff 4/5 + let t499 = circuit_add(t421, t432); // Fp6 add coeff 5/5 + let t500 = circuit_mul(t494, t284); // Fp2 mul start + let t501 = circuit_mul(t495, t285); + let t502 = circuit_sub(t500, t501); // Fp2 mul real part end + let t503 = circuit_mul(t494, t285); + let t504 = circuit_mul(t495, t284); + let t505 = circuit_add(t503, t504); // Fp2 mul imag part end + let t506 = circuit_mul(t496, t493); // Fp2 mul start + let t507 = circuit_mul(t497, t287); + let t508 = circuit_sub(t506, t507); // Fp2 mul real part end + let t509 = circuit_mul(t496, t287); + let t510 = circuit_mul(t497, t493); + let t511 = circuit_add(t509, t510); // Fp2 mul imag part end + let t512 = circuit_add(t496, t498); // Fp2 add coeff 0/1 + let t513 = circuit_add(t497, t499); // Fp2 add coeff 1/1 + let t514 = circuit_mul(t493, t512); // Fp2 mul start + let t515 = circuit_mul(t287, t513); + let t516 = circuit_sub(t514, t515); // Fp2 mul real part end + let t517 = circuit_mul(t493, t513); + let t518 = circuit_mul(t287, t512); + let t519 = circuit_add(t517, t518); // Fp2 mul imag part end + let t520 = circuit_sub(t516, t508); // Fp2 sub coeff 0/1 + let t521 = circuit_sub(t519, t511); // Fp2 sub coeff 1/1 + let t522 = circuit_add(t520, t521); + let t523 = circuit_add(t522, t522); + let t524 = circuit_sub(t520, t521); + let t525 = circuit_sub(t523, t520); + let t526 = circuit_sub(t525, t521); + let t527 = circuit_add(t524, t502); // Fp2 add coeff 0/1 + let t528 = circuit_add(t526, t505); // Fp2 add coeff 1/1 + let t529 = circuit_add(t494, t498); // Fp2 add coeff 0/1 + let t530 = circuit_add(t495, t499); // Fp2 add coeff 1/1 + let t531 = circuit_mul(t284, t529); // Fp2 mul start + let t532 = circuit_mul(t285, t530); + let t533 = circuit_sub(t531, t532); // Fp2 mul real part end + let t534 = circuit_mul(t284, t530); + let t535 = circuit_mul(t285, t529); + let t536 = circuit_add(t534, t535); // Fp2 mul imag part end + let t537 = circuit_sub(t533, t502); // Fp2 sub coeff 0/1 + let t538 = circuit_sub(t536, t505); // Fp2 sub coeff 1/1 + let t539 = circuit_add(t537, t508); // Fp2 add coeff 0/1 + let t540 = circuit_add(t538, t511); // Fp2 add coeff 1/1 + let t541 = circuit_add(t284, t493); // Fp2 add coeff 0/1 + let t542 = circuit_add(t285, t287); // Fp2 add coeff 1/1 + let t543 = circuit_add(t494, t496); // Fp2 add coeff 0/1 + let t544 = circuit_add(t495, t497); // Fp2 add coeff 1/1 + let t545 = circuit_mul(t541, t543); // Fp2 mul start + let t546 = circuit_mul(t542, t544); + let t547 = circuit_sub(t545, t546); // Fp2 mul real part end + let t548 = circuit_mul(t541, t544); + let t549 = circuit_mul(t542, t543); + let t550 = circuit_add(t548, t549); // Fp2 mul imag part end + let t551 = circuit_sub(t547, t502); // Fp2 sub coeff 0/1 + let t552 = circuit_sub(t550, t505); // Fp2 sub coeff 1/1 + let t553 = circuit_sub(t551, t508); // Fp2 sub coeff 0/1 + let t554 = circuit_sub(t552, t511); // Fp2 sub coeff 1/1 + let t555 = circuit_sub(t527, t460); // Fp6 sub coeff 0/5 + let t556 = circuit_sub(t528, t461); // Fp6 sub coeff 1/5 + let t557 = circuit_sub(t553, t486); // Fp6 sub coeff 2/5 + let t558 = circuit_sub(t554, t487); // Fp6 sub coeff 3/5 + let t559 = circuit_sub(t539, t472); // Fp6 sub coeff 4/5 + let t560 = circuit_sub(t540, t473); // Fp6 sub coeff 5/5 + let t561 = circuit_sub(t555, t490); // Fp6 sub coeff 0/5 + let t562 = circuit_sub(t556, t492); // Fp6 sub coeff 1/5 + let t563 = circuit_sub(t557, t416); // Fp6 sub coeff 2/5 + let t564 = circuit_sub(t558, t417); // Fp6 sub coeff 3/5 + let t565 = circuit_sub(t559, t418); // Fp6 sub coeff 4/5 + let t566 = circuit_sub(t560, t419); // Fp6 sub coeff 5/5 + let t567 = circuit_add(t418, t419); + let t568 = circuit_add(t567, t567); + let t569 = circuit_sub(t418, t419); + let t570 = circuit_sub(t568, t418); + let t571 = circuit_sub(t570, t419); + let t572 = circuit_add(t569, t460); // Fp6 add coeff 0/5 + let t573 = circuit_add(t571, t461); // Fp6 add coeff 1/5 + let t574 = circuit_add(t490, t486); // Fp6 add coeff 2/5 + let t575 = circuit_add(t492, t487); // Fp6 add coeff 3/5 + let t576 = circuit_add(t416, t472); // Fp6 add coeff 4/5 + let t577 = circuit_add(t417, t473); // Fp6 add coeff 5/5 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = ( + t260, + t261, + t270, + t271, + t572, + t573, + t574, + t575, + t576, + t577, + t561, + t562, + t563, + t564, + t565, + t566, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in1 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(yInv_0); // in2 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in3 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in4 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in5 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in6 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in7 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.x0); // in8 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.x1); // in9 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.y0); // in10 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.y1); // in11 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a0); // in12 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a1); // in13 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a0); // in14 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a1); // in15 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a0); // in16 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a1); // in17 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a0); // in18 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a1); // in19 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a0); // in20 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a1); // in21 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a0); // in22 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a1); // in23 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Q0: G2Point = G2Point { + x0: outputs.get_output(t260), + x1: outputs.get_output(t261), + y0: outputs.get_output(t270), + y1: outputs.get_output(t271) + }; + let Mi_plus_one: E12T = E12T { + c0b0a0: outputs.get_output(t572), + c0b0a1: outputs.get_output(t573), + c0b1a0: outputs.get_output(t574), + c0b1a1: outputs.get_output(t575), + c0b2a0: outputs.get_output(t576), + c0b2a1: outputs.get_output(t577), + c1b0a0: outputs.get_output(t561), + c1b0a1: outputs.get_output(t562), + c1b1a0: outputs.get_output(t563), + c1b1a1: outputs.get_output(t564), + c1b2a0: outputs.get_output(t565), + c1b2a1: outputs.get_output(t566), + }; + return (Q0, Mi_plus_one); +} +#[inline(always)] +fn run_BLS12_381_TOWER_MILLER_INIT_BIT_1P_circuit( + yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point +) -> (G2Point, u384, u384, u384, u384, u384, u384, u384, u384, u384, u384) { + // CONSTANT stack + let in0 = CE::> {}; // 0x3 + let in1 = CE::> {}; // 0x6 + let in2 = CE::> {}; // 0x0 + let in3 = CE::> {}; // 0x1 + + // INPUT stack + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let (in7, in8, in9) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in6, in7); + let t1 = circuit_sub(in6, in7); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in6, in7); + let t4 = circuit_mul(t2, in0); + let t5 = circuit_mul(t3, in1); + let t6 = circuit_add(in8, in8); // Fp2 add coeff 0/1 + let t7 = circuit_add(in9, in9); // Fp2 add coeff 1/1 + let t8 = circuit_mul(t6, t6); // Fp2 Inv start + let t9 = circuit_mul(t7, t7); + let t10 = circuit_add(t8, t9); + let t11 = circuit_inverse(t10); + let t12 = circuit_mul(t6, t11); // Fp2 Inv real part end + let t13 = circuit_mul(t7, t11); + let t14 = circuit_sub(in2, t13); // Fp2 Inv imag part end + let t15 = circuit_mul(t4, t12); // Fp2 mul start + let t16 = circuit_mul(t5, t14); + let t17 = circuit_sub(t15, t16); // Fp2 mul real part end + let t18 = circuit_mul(t4, t14); + let t19 = circuit_mul(t5, t12); + let t20 = circuit_add(t18, t19); // Fp2 mul imag part end + let t21 = circuit_mul(t17, in6); // Fp2 mul start + let t22 = circuit_mul(t20, in7); + let t23 = circuit_sub(t21, t22); // Fp2 mul real part end + let t24 = circuit_mul(t17, in7); + let t25 = circuit_mul(t20, in6); + let t26 = circuit_add(t24, t25); // Fp2 mul imag part end + let t27 = circuit_sub(t23, in8); // Fp2 sub coeff 0/1 + let t28 = circuit_sub(t26, in9); // Fp2 sub coeff 1/1 + let t29 = circuit_add(t17, t20); + let t30 = circuit_sub(t17, t20); + let t31 = circuit_mul(t29, t30); + let t32 = circuit_mul(t17, t20); + let t33 = circuit_add(t32, t32); + let t34 = circuit_add(in6, in6); // Fp2 add coeff 0/1 + let t35 = circuit_add(in7, in7); // Fp2 add coeff 1/1 + let t36 = circuit_sub(t31, t34); // Fp2 sub coeff 0/1 + let t37 = circuit_sub(t33, t35); // Fp2 sub coeff 1/1 + let t38 = circuit_sub(in6, t36); // Fp2 sub coeff 0/1 + let t39 = circuit_sub(in7, t37); // Fp2 sub coeff 1/1 + let t40 = circuit_mul(t38, t38); // Fp2 Inv start + let t41 = circuit_mul(t39, t39); + let t42 = circuit_add(t40, t41); + let t43 = circuit_inverse(t42); + let t44 = circuit_mul(t38, t43); // Fp2 Inv real part end + let t45 = circuit_mul(t39, t43); + let t46 = circuit_sub(in2, t45); // Fp2 Inv imag part end + let t47 = circuit_mul(t6, t44); // Fp2 mul start + let t48 = circuit_mul(t7, t46); + let t49 = circuit_sub(t47, t48); // Fp2 mul real part end + let t50 = circuit_mul(t6, t46); + let t51 = circuit_mul(t7, t44); + let t52 = circuit_add(t50, t51); // Fp2 mul imag part end + let t53 = circuit_sub(t49, t17); // Fp2 sub coeff 0/1 + let t54 = circuit_sub(t52, t20); // Fp2 sub coeff 1/1 + let t55 = circuit_mul(t53, in6); // Fp2 mul start + let t56 = circuit_mul(t54, in7); + let t57 = circuit_sub(t55, t56); // Fp2 mul real part end + let t58 = circuit_mul(t53, in7); + let t59 = circuit_mul(t54, in6); + let t60 = circuit_add(t58, t59); // Fp2 mul imag part end + let t61 = circuit_sub(t57, in8); // Fp2 sub coeff 0/1 + let t62 = circuit_sub(t60, in9); // Fp2 sub coeff 1/1 + let t63 = circuit_add(t53, t54); + let t64 = circuit_sub(t53, t54); + let t65 = circuit_mul(t63, t64); + let t66 = circuit_mul(t53, t54); + let t67 = circuit_add(t66, t66); + let t68 = circuit_add(in6, t36); // Fp2 add coeff 0/1 + let t69 = circuit_add(in7, t37); // Fp2 add coeff 1/1 + let t70 = circuit_sub(t65, t68); // Fp2 sub coeff 0/1 + let t71 = circuit_sub(t67, t69); // Fp2 sub coeff 1/1 + let t72 = circuit_sub(in6, t70); // Fp2 sub coeff 0/1 + let t73 = circuit_sub(in7, t71); // Fp2 sub coeff 1/1 + let t74 = circuit_mul(t53, t72); // Fp2 mul start + let t75 = circuit_mul(t54, t73); + let t76 = circuit_sub(t74, t75); // Fp2 mul real part end + let t77 = circuit_mul(t53, t73); + let t78 = circuit_mul(t54, t72); + let t79 = circuit_add(t77, t78); // Fp2 mul imag part end + let t80 = circuit_sub(t76, in8); // Fp2 sub coeff 0/1 + let t81 = circuit_sub(t79, in9); // Fp2 sub coeff 1/1 + let t82 = circuit_mul(t27, in4); + let t83 = circuit_mul(t28, in4); + let t84 = circuit_mul(t17, in5); + let t85 = circuit_mul(t20, in5); + let t86 = circuit_mul(t61, in4); + let t87 = circuit_mul(t62, in4); + let t88 = circuit_mul(t53, in5); + let t89 = circuit_mul(t54, in5); + let t90 = circuit_mul(t86, t82); // Fp2 mul start + let t91 = circuit_mul(t87, t83); + let t92 = circuit_sub(t90, t91); // Fp2 mul real part end + let t93 = circuit_mul(t86, t83); + let t94 = circuit_mul(t87, t82); + let t95 = circuit_add(t93, t94); // Fp2 mul imag part end + let t96 = circuit_mul(t88, t84); // Fp2 mul start + let t97 = circuit_mul(t89, t85); + let t98 = circuit_sub(t96, t97); // Fp2 mul real part end + let t99 = circuit_mul(t88, t85); + let t100 = circuit_mul(t89, t84); + let t101 = circuit_add(t99, t100); // Fp2 mul imag part end + let t102 = circuit_add(t82, t86); // Fp2 add coeff 0/1 + let t103 = circuit_add(t83, t87); // Fp2 add coeff 1/1 + let t104 = circuit_add(t86, t88); // Fp2 add coeff 0/1 + let t105 = circuit_add(t87, t89); // Fp2 add coeff 1/1 + let t106 = circuit_add(t82, t84); // Fp2 add coeff 0/1 + let t107 = circuit_add(t83, t85); // Fp2 add coeff 1/1 + let t108 = circuit_mul(t106, t104); // Fp2 mul start + let t109 = circuit_mul(t107, t105); + let t110 = circuit_sub(t108, t109); // Fp2 mul real part end + let t111 = circuit_mul(t106, t105); + let t112 = circuit_mul(t107, t104); + let t113 = circuit_add(t111, t112); // Fp2 mul imag part end + let t114 = circuit_sub(t110, t92); // Fp2 sub coeff 0/1 + let t115 = circuit_sub(t113, t95); // Fp2 sub coeff 1/1 + let t116 = circuit_sub(t114, t98); // Fp2 sub coeff 0/1 + let t117 = circuit_sub(t115, t101); // Fp2 sub coeff 1/1 + let t118 = circuit_add(t84, t88); // Fp2 add coeff 0/1 + let t119 = circuit_add(t85, t89); // Fp2 add coeff 1/1 + let t120 = circuit_add(in3, in2); + let t121 = circuit_add(t120, t120); + let t122 = circuit_sub(in3, in2); + let t123 = circuit_sub(t121, in3); + let t124 = circuit_sub(t123, in2); + let t125 = circuit_add(t122, t92); // Fp2 add coeff 0/1 + let t126 = circuit_add(t124, t95); // Fp2 add coeff 1/1 + + let modulus = get_BLS12_381_modulus(); // BLS12_381 prime field modulus + + let mut circuit_inputs = ( + t70, t71, t80, t81, t125, t126, t116, t117, t98, t101, t102, t103, t118, t119, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x3, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x6, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in2 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in3 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(yInv_0); // in4 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in5 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in6 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in7 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in8 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in9 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Q0: G2Point = G2Point { + x0: outputs.get_output(t70), + x1: outputs.get_output(t71), + y0: outputs.get_output(t80), + y1: outputs.get_output(t81) + }; + let c0b0a0: u384 = outputs.get_output(t125); + let c0b0a1: u384 = outputs.get_output(t126); + let c0b1a0: u384 = outputs.get_output(t116); + let c0b1a1: u384 = outputs.get_output(t117); + let c0b2a0: u384 = outputs.get_output(t98); + let c0b2a1: u384 = outputs.get_output(t101); + let c1b1a0: u384 = outputs.get_output(t102); + let c1b1a1: u384 = outputs.get_output(t103); + let c1b2a0: u384 = outputs.get_output(t118); + let c1b2a1: u384 = outputs.get_output(t119); + return (Q0, c0b0a0, c0b0a1, c0b1a0, c0b1a1, c0b2a0, c0b2a1, c1b1a0, c1b1a1, c1b2a0, c1b2a1); +} +#[inline(always)] +fn run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0xa + let in1 = CE::> {}; // 0x9 + + // INPUT stack + let (in2, in3, in4) = (CE::> {}, CE::> {}, CE::> {}); + let (in5, in6, in7) = (CE::> {}, CE::> {}, CE::> {}); + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in10, in11); + let t1 = circuit_sub(in10, in11); + let t2 = circuit_mul(t0, t1); + let t3 = circuit_mul(in10, in11); + let t4 = circuit_add(t3, t3); + let t5 = circuit_add(in2, in3); + let t6 = circuit_sub(in2, in3); + let t7 = circuit_mul(t5, t6); + let t8 = circuit_mul(in2, in3); + let t9 = circuit_add(t8, t8); + let t10 = circuit_add(in10, in2); // Fp2 add coeff 0/1 + let t11 = circuit_add(in11, in3); // Fp2 add coeff 1/1 + let t12 = circuit_add(t10, t11); + let t13 = circuit_sub(t10, t11); + let t14 = circuit_mul(t12, t13); + let t15 = circuit_mul(t10, t11); + let t16 = circuit_add(t15, t15); + let t17 = circuit_sub(t14, t2); // Fp2 sub coeff 0/1 + let t18 = circuit_sub(t16, t4); // Fp2 sub coeff 1/1 + let t19 = circuit_sub(t17, t7); // Fp2 sub coeff 0/1 + let t20 = circuit_sub(t18, t9); // Fp2 sub coeff 1/1 + let t21 = circuit_add(in6, in7); + let t22 = circuit_sub(in6, in7); + let t23 = circuit_mul(t21, t22); + let t24 = circuit_mul(in6, in7); + let t25 = circuit_add(t24, t24); + let t26 = circuit_add(in8, in9); + let t27 = circuit_sub(in8, in9); + let t28 = circuit_mul(t26, t27); + let t29 = circuit_mul(in8, in9); + let t30 = circuit_add(t29, t29); + let t31 = circuit_add(in6, in8); // Fp2 add coeff 0/1 + let t32 = circuit_add(in7, in9); // Fp2 add coeff 1/1 + let t33 = circuit_add(t31, t32); + let t34 = circuit_sub(t31, t32); + let t35 = circuit_mul(t33, t34); + let t36 = circuit_mul(t31, t32); + let t37 = circuit_add(t36, t36); + let t38 = circuit_sub(t35, t23); // Fp2 sub coeff 0/1 + let t39 = circuit_sub(t37, t25); // Fp2 sub coeff 1/1 + let t40 = circuit_sub(t38, t28); // Fp2 sub coeff 0/1 + let t41 = circuit_sub(t39, t30); // Fp2 sub coeff 1/1 + let t42 = circuit_add(in12, in13); + let t43 = circuit_sub(in12, in13); + let t44 = circuit_mul(t42, t43); + let t45 = circuit_mul(in12, in13); + let t46 = circuit_add(t45, t45); + let t47 = circuit_add(in4, in5); + let t48 = circuit_sub(in4, in5); + let t49 = circuit_mul(t47, t48); + let t50 = circuit_mul(in4, in5); + let t51 = circuit_add(t50, t50); + let t52 = circuit_add(in12, in4); // Fp2 add coeff 0/1 + let t53 = circuit_add(in13, in5); // Fp2 add coeff 1/1 + let t54 = circuit_add(t52, t53); + let t55 = circuit_sub(t52, t53); + let t56 = circuit_mul(t54, t55); + let t57 = circuit_mul(t52, t53); + let t58 = circuit_add(t57, t57); + let t59 = circuit_sub(t56, t44); // Fp2 sub coeff 0/1 + let t60 = circuit_sub(t58, t46); // Fp2 sub coeff 1/1 + let t61 = circuit_sub(t59, t49); // Fp2 sub coeff 0/1 + let t62 = circuit_sub(t60, t51); // Fp2 sub coeff 1/1 + let t63 = circuit_add(t61, t62); + let t64 = circuit_mul(t63, in0); + let t65 = circuit_mul(t61, in1); + let t66 = circuit_sub(t65, t62); + let t67 = circuit_sub(t64, t65); + let t68 = circuit_sub(t67, t62); + let t69 = circuit_add(t2, t4); + let t70 = circuit_mul(t69, in0); + let t71 = circuit_mul(t2, in1); + let t72 = circuit_sub(t71, t4); + let t73 = circuit_sub(t70, t71); + let t74 = circuit_sub(t73, t4); + let t75 = circuit_add(t72, t7); // Fp2 add coeff 0/1 + let t76 = circuit_add(t74, t9); // Fp2 add coeff 1/1 + let t77 = circuit_add(t23, t25); + let t78 = circuit_mul(t77, in0); + let t79 = circuit_mul(t23, in1); + let t80 = circuit_sub(t79, t25); + let t81 = circuit_sub(t78, t79); + let t82 = circuit_sub(t81, t25); + let t83 = circuit_add(t80, t28); // Fp2 add coeff 0/1 + let t84 = circuit_add(t82, t30); // Fp2 add coeff 1/1 + let t85 = circuit_add(t44, t46); + let t86 = circuit_mul(t85, in0); + let t87 = circuit_mul(t44, in1); + let t88 = circuit_sub(t87, t46); + let t89 = circuit_sub(t86, t87); + let t90 = circuit_sub(t89, t46); + let t91 = circuit_add(t88, t49); // Fp2 add coeff 0/1 + let t92 = circuit_add(t90, t51); // Fp2 add coeff 1/1 + let t93 = circuit_sub(t75, in2); // Fp2 sub coeff 0/1 + let t94 = circuit_sub(t76, in3); // Fp2 sub coeff 1/1 + let t95 = circuit_add(t93, t93); // Fp2 add coeff 0/1 + let t96 = circuit_add(t94, t94); // Fp2 add coeff 1/1 + let t97 = circuit_add(t95, t75); // Fp2 add coeff 0/1 + let t98 = circuit_add(t96, t76); // Fp2 add coeff 1/1 + let t99 = circuit_sub(t83, in4); // Fp2 sub coeff 0/1 + let t100 = circuit_sub(t84, in5); // Fp2 sub coeff 1/1 + let t101 = circuit_add(t99, t99); // Fp2 add coeff 0/1 + let t102 = circuit_add(t100, t100); // Fp2 add coeff 1/1 + let t103 = circuit_add(t101, t83); // Fp2 add coeff 0/1 + let t104 = circuit_add(t102, t84); // Fp2 add coeff 1/1 + let t105 = circuit_sub(t91, in6); // Fp2 sub coeff 0/1 + let t106 = circuit_sub(t92, in7); // Fp2 sub coeff 1/1 + let t107 = circuit_add(t105, t105); // Fp2 add coeff 0/1 + let t108 = circuit_add(t106, t106); // Fp2 add coeff 1/1 + let t109 = circuit_add(t107, t91); // Fp2 add coeff 0/1 + let t110 = circuit_add(t108, t92); // Fp2 add coeff 1/1 + let t111 = circuit_add(t66, in8); // Fp2 add coeff 0/1 + let t112 = circuit_add(t68, in9); // Fp2 add coeff 1/1 + let t113 = circuit_add(t111, t111); // Fp2 add coeff 0/1 + let t114 = circuit_add(t112, t112); // Fp2 add coeff 1/1 + let t115 = circuit_add(t113, t66); // Fp2 add coeff 0/1 + let t116 = circuit_add(t114, t68); // Fp2 add coeff 1/1 + let t117 = circuit_add(t19, in10); // Fp2 add coeff 0/1 + let t118 = circuit_add(t20, in11); // Fp2 add coeff 1/1 + let t119 = circuit_add(t117, t117); // Fp2 add coeff 0/1 + let t120 = circuit_add(t118, t118); // Fp2 add coeff 1/1 + let t121 = circuit_add(t119, t19); // Fp2 add coeff 0/1 + let t122 = circuit_add(t120, t20); // Fp2 add coeff 1/1 + let t123 = circuit_add(t40, in12); // Fp2 add coeff 0/1 + let t124 = circuit_add(t41, in13); // Fp2 add coeff 1/1 + let t125 = circuit_add(t123, t123); // Fp2 add coeff 0/1 + let t126 = circuit_add(t124, t124); // Fp2 add coeff 1/1 + let t127 = circuit_add(t125, t40); // Fp2 add coeff 0/1 + let t128 = circuit_add(t126, t41); // Fp2 add coeff 1/1 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = (t97, t98, t103, t104, t109, t110, t115, t116, t121, t122, t127, t128,) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0xa, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x9, 0x0, 0x0, 0x0]); // in1 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in2 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in3 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in4 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in5 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in6 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in7 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in8 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in9 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in10 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in12 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in13 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t97), + c0b0a1: outputs.get_output(t98), + c0b1a0: outputs.get_output(t103), + c0b1a1: outputs.get_output(t104), + c0b2a0: outputs.get_output(t109), + c0b2a1: outputs.get_output(t110), + c1b0a0: outputs.get_output(t115), + c1b0a1: outputs.get_output(t116), + c1b1a0: outputs.get_output(t121), + c1b1a1: outputs.get_output(t122), + c1b2a0: outputs.get_output(t127), + c1b2a1: outputs.get_output(t128), + }; + return (res,); +} +#[inline(always)] +fn run_BN254_E12T_FROBENIUS_CUBE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d + let in2 = CE::> {}; // 0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de + let in3 = CE::> {}; // 0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066 + let in4 = CE::> {}; // 0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f + let in5 = CE::> {}; // 0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f + let in6 = CE::> {}; // 0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101 + let in7 = CE::> {}; // 0x2a275b6d9896aa4cdbf17f1dca9e5ea3bbd689a3bea870f45fcc8ad066dce9ed + let in8 = CE::> {}; // 0x28a411b634f09b8fb14b900e9507e9327600ecc7d8cf6ebab94d0cb3b2594c64 + let in9 = CE::> {}; // 0x13c49044952c0905711699fa3b4d3f692ed68098967c84a5ebde847076261b43 + let in10 = CE::< + CI<10> + > {}; // 0x16db366a59b1dd0b9fb1b2282a48633d3e2ddaea200280211f25041384282499 + + // INPUT stack + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let (in17, in18, in19) = (CE::> {}, CE::> {}, CE::> {}); + let (in20, in21, in22) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in0, in12); + let t1 = circuit_add(in11, in0); + let t2 = circuit_sub(in0, in14); + let t3 = circuit_sub(in0, in16); + let t4 = circuit_sub(in0, in18); + let t5 = circuit_sub(in0, in20); + let t6 = circuit_sub(in0, in22); + let t7 = circuit_mul(in1, in13); // Fp2 mul start + let t8 = circuit_mul(in2, t2); + let t9 = circuit_sub(t7, t8); // Fp2 mul real part end + let t10 = circuit_mul(in1, t2); + let t11 = circuit_mul(in2, in13); + let t12 = circuit_add(t10, t11); // Fp2 mul imag part end + let t13 = circuit_mul(in3, in15); // Fp2 mul start + let t14 = circuit_mul(in4, t3); + let t15 = circuit_sub(t13, t14); // Fp2 mul real part end + let t16 = circuit_mul(in3, t3); + let t17 = circuit_mul(in4, in15); + let t18 = circuit_add(t16, t17); // Fp2 mul imag part end + let t19 = circuit_mul(in5, in17); // Fp2 mul start + let t20 = circuit_mul(in6, t4); + let t21 = circuit_sub(t19, t20); // Fp2 mul real part end + let t22 = circuit_mul(in5, t4); + let t23 = circuit_mul(in6, in17); + let t24 = circuit_add(t22, t23); // Fp2 mul imag part end + let t25 = circuit_mul(in7, in19); // Fp2 mul start + let t26 = circuit_mul(in8, t5); + let t27 = circuit_sub(t25, t26); // Fp2 mul real part end + let t28 = circuit_mul(in7, t5); + let t29 = circuit_mul(in8, in19); + let t30 = circuit_add(t28, t29); // Fp2 mul imag part end + let t31 = circuit_mul(in9, in21); // Fp2 mul start + let t32 = circuit_mul(in10, t6); + let t33 = circuit_sub(t31, t32); // Fp2 mul real part end + let t34 = circuit_mul(in9, t6); + let t35 = circuit_mul(in10, in21); + let t36 = circuit_add(t34, t35); // Fp2 mul imag part end + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = (t1, t0, t9, t12, t15, t18, t21, t24, t27, t30, t33, t36,) + .new_inputs(); + // Prefill constants: + + circuit_inputs = circuit_inputs + .next_span(E12T_FROBENIUS_CUBE_BN254_CONSTANTS.span()); // in0 - in10 + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in11 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in12 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in13 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in14 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in15 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in16 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in17 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in18 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in19 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in20 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in21 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in22 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t1), + c0b0a1: outputs.get_output(t0), + c0b1a0: outputs.get_output(t9), + c0b1a1: outputs.get_output(t12), + c0b2a0: outputs.get_output(t15), + c0b2a1: outputs.get_output(t18), + c1b0a0: outputs.get_output(t21), + c1b0a1: outputs.get_output(t24), + c1b1a0: outputs.get_output(t27), + c1b1a1: outputs.get_output(t30), + c1b2a0: outputs.get_output(t33), + c1b2a1: outputs.get_output(t36), + }; + return (res,); +} +const E12T_FROBENIUS_CUBE_BN254_CONSTANTS: [ + u384 + ; 11] = [ + u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { + limb0: 0x5d6942d37b746ee87bdcfb6d, + limb1: 0xbaff1c77959f25ac805ffd3d, + limb2: 0x856e078b755ef0a, + limb3: 0x0 + }, + u384 { + limb0: 0x98ff2631380cab2baaa586de, + limb1: 0xa9f30e6dec26094f0fdf31bf, + limb2: 0x4f1de41b3d1766f, + limb3: 0x0 + }, + u384 { + limb0: 0x75b06bcb0e1a92bc3ccbf066, + limb1: 0x19bee0f7b5b2444ee6330945, + limb2: 0xbc58c6611c08dab, + limb3: 0x0 + }, + u384 { + limb0: 0x737f96e55fe3ed9d730c239f, + limb1: 0xfeb0f6ef0cd21d04a44a9e08, + limb2: 0x23d5e999e1910a12, + limb3: 0x0 + }, + u384 { + limb0: 0xbe55d24ae86f7d391ed4a67f, + limb1: 0xefe9608cd0acaa90894cb38d, + limb2: 0x19dc81cfcc82e4bb, + limb3: 0x0 + }, + u384 { + limb0: 0x97d439ec7694aa2bf4c0c101, + limb1: 0x6cbeee33576139d7f03a5e3, + limb2: 0xabf8b60be77d73, + limb3: 0x0 + }, + u384 { + limb0: 0xbea870f45fcc8ad066dce9ed, + limb1: 0xdbf17f1dca9e5ea3bbd689a3, + limb2: 0x2a275b6d9896aa4c, + limb3: 0x0 + }, + u384 { + limb0: 0xd8cf6ebab94d0cb3b2594c64, + limb1: 0xb14b900e9507e9327600ecc7, + limb2: 0x28a411b634f09b8f, + limb3: 0x0 + }, + u384 { + limb0: 0x967c84a5ebde847076261b43, + limb1: 0x711699fa3b4d3f692ed68098, + limb2: 0x13c49044952c0905, + limb3: 0x0 + }, + u384 { + limb0: 0x200280211f25041384282499, + limb1: 0x9fb1b2282a48633d3e2ddaea, + limb2: 0x16db366a59b1dd0b, + limb3: 0x0 + } +]; +#[inline(always)] +fn run_BN254_E12T_FROBENIUS_SQUARE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48 + let in2 = CE::> {}; // 0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe + let in3 = CE::> {}; // 0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49 + let in4 = CE::> {}; // -0x1 % p + let in5 = CE::> {}; // 0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff + + // INPUT stack + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let (in15, in16, in17) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in6, in0); + let t1 = circuit_add(in7, in0); + let t2 = circuit_mul(in1, in8); + let t3 = circuit_mul(in1, in9); + let t4 = circuit_mul(in2, in10); + let t5 = circuit_mul(in2, in11); + let t6 = circuit_mul(in3, in12); + let t7 = circuit_mul(in3, in13); + let t8 = circuit_mul(in4, in14); + let t9 = circuit_mul(in4, in15); + let t10 = circuit_mul(in5, in16); + let t11 = circuit_mul(in5, in17); + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs + .next_2( + [0xbb966e3de4bd44e5607cfd48, 0x5e6dd9e7e0acccb0c28f069f, 0x30644e72e131a029, 0x0] + ); // in1 + circuit_inputs = circuit_inputs + .next_2([0xacdb5c4f5763473177fffffe, 0x59e26bcea0d48bacd4f263f1, 0x0, 0x0]); // in2 + circuit_inputs = circuit_inputs + .next_2( + [0xbb966e3de4bd44e5607cfd49, 0x5e6dd9e7e0acccb0c28f069f, 0x30644e72e131a029, 0x0] + ); // in3 + circuit_inputs = circuit_inputs + .next_2( + [0x6871ca8d3c208c16d87cfd46, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0] + ); // in4 + circuit_inputs = circuit_inputs + .next_2([0xacdb5c4f5763473177ffffff, 0x59e26bcea0d48bacd4f263f1, 0x0, 0x0]); // in5 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in6 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in7 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in8 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in9 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in10 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in12 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in13 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in14 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in15 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in16 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in17 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t0), + c0b0a1: outputs.get_output(t1), + c0b1a0: outputs.get_output(t2), + c0b1a1: outputs.get_output(t3), + c0b2a0: outputs.get_output(t4), + c0b2a1: outputs.get_output(t5), + c1b0a0: outputs.get_output(t6), + c1b0a1: outputs.get_output(t7), + c1b1a0: outputs.get_output(t8), + c1b1a1: outputs.get_output(t9), + c1b2a0: outputs.get_output(t10), + c1b2a1: outputs.get_output(t11), + }; + return (res,); +} +#[inline(always)] +fn run_BN254_E12T_FROBENIUS_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + let in1 = CE::> {}; // 0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d + let in2 = CE::> {}; // 0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2 + let in3 = CE::> {}; // 0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762 + let in4 = CE::> {}; // 0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126 + let in5 = CE::> {}; // 0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470 + let in6 = CE::> {}; // 0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac + let in7 = CE::> {}; // 0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a + let in8 = CE::> {}; // 0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3 + let in9 = CE::> {}; // 0x183c1e74f798649e93a3661a4353ff4425c459b55aa1bd32ea2c810eab7692f + let in10 = CE::< + CI<10> + > {}; // 0x12acf2ca76fd0675a27fb246c7729f7db080cb99678e2ac024c6b8ee6e0c2c4b + + // INPUT stack + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let (in17, in18, in19) = (CE::> {}, CE::> {}, CE::> {}); + let (in20, in21, in22) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in0, in12); + let t1 = circuit_add(in11, in0); + let t2 = circuit_sub(in0, in14); + let t3 = circuit_sub(in0, in16); + let t4 = circuit_sub(in0, in18); + let t5 = circuit_sub(in0, in20); + let t6 = circuit_sub(in0, in22); + let t7 = circuit_mul(in1, in13); // Fp2 mul start + let t8 = circuit_mul(in2, t2); + let t9 = circuit_sub(t7, t8); // Fp2 mul real part end + let t10 = circuit_mul(in1, t2); + let t11 = circuit_mul(in2, in13); + let t12 = circuit_add(t10, t11); // Fp2 mul imag part end + let t13 = circuit_mul(in3, in15); // Fp2 mul start + let t14 = circuit_mul(in4, t3); + let t15 = circuit_sub(t13, t14); // Fp2 mul real part end + let t16 = circuit_mul(in3, t3); + let t17 = circuit_mul(in4, in15); + let t18 = circuit_add(t16, t17); // Fp2 mul imag part end + let t19 = circuit_mul(in5, in17); // Fp2 mul start + let t20 = circuit_mul(in6, t4); + let t21 = circuit_sub(t19, t20); // Fp2 mul real part end + let t22 = circuit_mul(in5, t4); + let t23 = circuit_mul(in6, in17); + let t24 = circuit_add(t22, t23); // Fp2 mul imag part end + let t25 = circuit_mul(in7, in19); // Fp2 mul start + let t26 = circuit_mul(in8, t5); + let t27 = circuit_sub(t25, t26); // Fp2 mul real part end + let t28 = circuit_mul(in7, t5); + let t29 = circuit_mul(in8, in19); + let t30 = circuit_add(t28, t29); // Fp2 mul imag part end + let t31 = circuit_mul(in9, in21); // Fp2 mul start + let t32 = circuit_mul(in10, t6); + let t33 = circuit_sub(t31, t32); // Fp2 mul real part end + let t34 = circuit_mul(in9, t6); + let t35 = circuit_mul(in10, in21); + let t36 = circuit_add(t34, t35); // Fp2 mul imag part end + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = (t1, t0, t9, t12, t15, t18, t21, t24, t27, t30, t33, t36,) + .new_inputs(); + // Prefill constants: + + circuit_inputs = circuit_inputs.next_span(E12T_FROBENIUS_BN254_CONSTANTS.span()); // in0 - in10 + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in11 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in12 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in13 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in14 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in15 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in16 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in17 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in18 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in19 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in20 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in21 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in22 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t1), + c0b0a1: outputs.get_output(t0), + c0b1a0: outputs.get_output(t9), + c0b1a1: outputs.get_output(t12), + c0b2a0: outputs.get_output(t15), + c0b2a1: outputs.get_output(t18), + c1b0a0: outputs.get_output(t21), + c1b0a1: outputs.get_output(t24), + c1b1a0: outputs.get_output(t27), + c1b1a1: outputs.get_output(t30), + c1b2a0: outputs.get_output(t33), + c1b2a1: outputs.get_output(t36), + }; + return (res,); +} +const E12T_FROBENIUS_BN254_CONSTANTS: [ + u384 + ; 11] = [ + u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { + limb0: 0xc2c3330c99e39557176f553d, + limb1: 0x4c0bec3cf559b143b78cc310, + limb2: 0x2fb347984f7911f7, + limb3: 0x0 + }, + u384 { + limb0: 0xb7c9dce1665d51c640fcba2, + limb1: 0x4ba4cc8bd75a079432ae2a1d, + limb2: 0x16c9e55061ebae20, + limb3: 0x0 + }, + u384 { + limb0: 0xbe94ec72848a1f55921ea762, + limb1: 0x80f3c0b75a181e84d33365f7, + limb2: 0x5b54f5e64eea801, + limb3: 0x0 + }, + u384 { + limb0: 0x1bdec763c13b4711cd2b8126, + limb1: 0x9f3a80b03b0b1c923685d2ea, + limb2: 0x2c145edbe7fd8aee, + limb3: 0x0 + }, + u384 { + limb0: 0x292f2176d60b35dadcc9e470, + limb1: 0xe8b99fdd76e68b605c521e08, + limb2: 0x1284b71c2865a7df, + limb3: 0x0 + }, + u384 { + limb0: 0x8eeec7e5ca5cf05f80f362ac, + limb1: 0xa6327cfe12150b8e74799277, + limb2: 0x246996f3b4fae7e6, + limb3: 0x0 + }, + u384 { + limb0: 0xa9c95998dc54014671a0135a, + limb1: 0xdc5ec698b6e2f9b9dbaae0ed, + limb2: 0x63cf305489af5dc, + limb3: 0x0 + }, + u384 { + limb0: 0x8fa25bd282d37f632623b0e3, + limb1: 0x704b5a7ec796f2b21807dc9, + limb2: 0x7c03cbcac41049a, + limb3: 0x0 + }, + u384 { + limb0: 0x55aa1bd32ea2c810eab7692f, + limb1: 0xe93a3661a4353ff4425c459b, + limb2: 0x183c1e74f798649, + limb3: 0x0 + }, + u384 { + limb0: 0x678e2ac024c6b8ee6e0c2c4b, + limb1: 0xa27fb246c7729f7db080cb99, + limb2: 0x12acf2ca76fd0675, + limb3: 0x0 + } +]; +#[inline(always)] +fn run_BN254_E12T_INVERSE_circuit(M: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0xa + let in1 = CE::> {}; // 0x9 + let in2 = CE::> {}; // 0x0 + + // INPUT stack + let (in3, in4, in5) = (CE::> {}, CE::> {}, CE::> {}); + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_mul(in3, in5); // Fp2 mul start + let t1 = circuit_mul(in4, in6); + let t2 = circuit_sub(t0, t1); // Fp2 mul real part end + let t3 = circuit_mul(in3, in6); + let t4 = circuit_mul(in4, in5); + let t5 = circuit_add(t3, t4); // Fp2 mul imag part end + let t6 = circuit_add(t2, t2); // Fp2 add coeff 0/1 + let t7 = circuit_add(t5, t5); // Fp2 add coeff 1/1 + let t8 = circuit_add(in7, in8); + let t9 = circuit_sub(in7, in8); + let t10 = circuit_mul(t8, t9); + let t11 = circuit_mul(in7, in8); + let t12 = circuit_add(t11, t11); + let t13 = circuit_add(t10, t12); + let t14 = circuit_mul(t13, in0); + let t15 = circuit_mul(t10, in1); + let t16 = circuit_sub(t15, t12); + let t17 = circuit_sub(t14, t15); + let t18 = circuit_sub(t17, t12); + let t19 = circuit_add(t16, t6); // Fp2 add coeff 0/1 + let t20 = circuit_add(t18, t7); // Fp2 add coeff 1/1 + let t21 = circuit_sub(t6, t10); // Fp2 sub coeff 0/1 + let t22 = circuit_sub(t7, t12); // Fp2 sub coeff 1/1 + let t23 = circuit_add(in3, in4); + let t24 = circuit_sub(in3, in4); + let t25 = circuit_mul(t23, t24); + let t26 = circuit_mul(in3, in4); + let t27 = circuit_add(t26, t26); + let t28 = circuit_sub(in3, in5); // Fp2 sub coeff 0/1 + let t29 = circuit_sub(in4, in6); // Fp2 sub coeff 1/1 + let t30 = circuit_add(t28, in7); // Fp2 add coeff 0/1 + let t31 = circuit_add(t29, in8); // Fp2 add coeff 1/1 + let t32 = circuit_mul(in5, in7); // Fp2 mul start + let t33 = circuit_mul(in6, in8); + let t34 = circuit_sub(t32, t33); // Fp2 mul real part end + let t35 = circuit_mul(in5, in8); + let t36 = circuit_mul(in6, in7); + let t37 = circuit_add(t35, t36); // Fp2 mul imag part end + let t38 = circuit_add(t34, t34); // Fp2 add coeff 0/1 + let t39 = circuit_add(t37, t37); // Fp2 add coeff 1/1 + let t40 = circuit_add(t30, t31); + let t41 = circuit_sub(t30, t31); + let t42 = circuit_mul(t40, t41); + let t43 = circuit_mul(t30, t31); + let t44 = circuit_add(t43, t43); + let t45 = circuit_add(t38, t39); + let t46 = circuit_mul(t45, in0); + let t47 = circuit_mul(t38, in1); + let t48 = circuit_sub(t47, t39); + let t49 = circuit_sub(t46, t47); + let t50 = circuit_sub(t49, t39); + let t51 = circuit_add(t48, t25); // Fp2 add coeff 0/1 + let t52 = circuit_add(t50, t27); // Fp2 add coeff 1/1 + let t53 = circuit_add(t21, t42); // Fp2 add coeff 0/1 + let t54 = circuit_add(t22, t44); // Fp2 add coeff 1/1 + let t55 = circuit_add(t53, t38); // Fp2 add coeff 0/1 + let t56 = circuit_add(t54, t39); // Fp2 add coeff 1/1 + let t57 = circuit_sub(t55, t25); // Fp2 sub coeff 0/1 + let t58 = circuit_sub(t56, t27); // Fp2 sub coeff 1/1 + let t59 = circuit_mul(in9, in11); // Fp2 mul start + let t60 = circuit_mul(in10, in12); + let t61 = circuit_sub(t59, t60); // Fp2 mul real part end + let t62 = circuit_mul(in9, in12); + let t63 = circuit_mul(in10, in11); + let t64 = circuit_add(t62, t63); // Fp2 mul imag part end + let t65 = circuit_add(t61, t61); // Fp2 add coeff 0/1 + let t66 = circuit_add(t64, t64); // Fp2 add coeff 1/1 + let t67 = circuit_add(in13, in14); + let t68 = circuit_sub(in13, in14); + let t69 = circuit_mul(t67, t68); + let t70 = circuit_mul(in13, in14); + let t71 = circuit_add(t70, t70); + let t72 = circuit_add(t69, t71); + let t73 = circuit_mul(t72, in0); + let t74 = circuit_mul(t69, in1); + let t75 = circuit_sub(t74, t71); + let t76 = circuit_sub(t73, t74); + let t77 = circuit_sub(t76, t71); + let t78 = circuit_add(t75, t65); // Fp2 add coeff 0/1 + let t79 = circuit_add(t77, t66); // Fp2 add coeff 1/1 + let t80 = circuit_sub(t65, t69); // Fp2 sub coeff 0/1 + let t81 = circuit_sub(t66, t71); // Fp2 sub coeff 1/1 + let t82 = circuit_add(in9, in10); + let t83 = circuit_sub(in9, in10); + let t84 = circuit_mul(t82, t83); + let t85 = circuit_mul(in9, in10); + let t86 = circuit_add(t85, t85); + let t87 = circuit_sub(in9, in11); // Fp2 sub coeff 0/1 + let t88 = circuit_sub(in10, in12); // Fp2 sub coeff 1/1 + let t89 = circuit_add(t87, in13); // Fp2 add coeff 0/1 + let t90 = circuit_add(t88, in14); // Fp2 add coeff 1/1 + let t91 = circuit_mul(in11, in13); // Fp2 mul start + let t92 = circuit_mul(in12, in14); + let t93 = circuit_sub(t91, t92); // Fp2 mul real part end + let t94 = circuit_mul(in11, in14); + let t95 = circuit_mul(in12, in13); + let t96 = circuit_add(t94, t95); // Fp2 mul imag part end + let t97 = circuit_add(t93, t93); // Fp2 add coeff 0/1 + let t98 = circuit_add(t96, t96); // Fp2 add coeff 1/1 + let t99 = circuit_add(t89, t90); + let t100 = circuit_sub(t89, t90); + let t101 = circuit_mul(t99, t100); + let t102 = circuit_mul(t89, t90); + let t103 = circuit_add(t102, t102); + let t104 = circuit_add(t97, t98); + let t105 = circuit_mul(t104, in0); + let t106 = circuit_mul(t97, in1); + let t107 = circuit_sub(t106, t98); + let t108 = circuit_sub(t105, t106); + let t109 = circuit_sub(t108, t98); + let t110 = circuit_add(t107, t84); // Fp2 add coeff 0/1 + let t111 = circuit_add(t109, t86); // Fp2 add coeff 1/1 + let t112 = circuit_add(t80, t101); // Fp2 add coeff 0/1 + let t113 = circuit_add(t81, t103); // Fp2 add coeff 1/1 + let t114 = circuit_add(t112, t97); // Fp2 add coeff 0/1 + let t115 = circuit_add(t113, t98); // Fp2 add coeff 1/1 + let t116 = circuit_sub(t114, t84); // Fp2 sub coeff 0/1 + let t117 = circuit_sub(t115, t86); // Fp2 sub coeff 1/1 + let t118 = circuit_add(t116, t117); + let t119 = circuit_mul(t118, in0); + let t120 = circuit_mul(t116, in1); + let t121 = circuit_sub(t120, t117); + let t122 = circuit_sub(t119, t120); + let t123 = circuit_sub(t122, t117); + let t124 = circuit_sub(t51, t121); // Fp6 sub coeff 0/5 + let t125 = circuit_sub(t52, t123); // Fp6 sub coeff 1/5 + let t126 = circuit_sub(t19, t110); // Fp6 sub coeff 2/5 + let t127 = circuit_sub(t20, t111); // Fp6 sub coeff 3/5 + let t128 = circuit_sub(t57, t78); // Fp6 sub coeff 4/5 + let t129 = circuit_sub(t58, t79); // Fp6 sub coeff 5/5 + let t130 = circuit_add(t124, t125); + let t131 = circuit_sub(t124, t125); + let t132 = circuit_mul(t130, t131); + let t133 = circuit_mul(t124, t125); + let t134 = circuit_add(t133, t133); + let t135 = circuit_add(t126, t127); + let t136 = circuit_sub(t126, t127); + let t137 = circuit_mul(t135, t136); + let t138 = circuit_mul(t126, t127); + let t139 = circuit_add(t138, t138); + let t140 = circuit_add(t128, t129); + let t141 = circuit_sub(t128, t129); + let t142 = circuit_mul(t140, t141); + let t143 = circuit_mul(t128, t129); + let t144 = circuit_add(t143, t143); + let t145 = circuit_mul(t124, t126); // Fp2 mul start + let t146 = circuit_mul(t125, t127); + let t147 = circuit_sub(t145, t146); // Fp2 mul real part end + let t148 = circuit_mul(t124, t127); + let t149 = circuit_mul(t125, t126); + let t150 = circuit_add(t148, t149); // Fp2 mul imag part end + let t151 = circuit_mul(t124, t128); // Fp2 mul start + let t152 = circuit_mul(t125, t129); + let t153 = circuit_sub(t151, t152); // Fp2 mul real part end + let t154 = circuit_mul(t124, t129); + let t155 = circuit_mul(t125, t128); + let t156 = circuit_add(t154, t155); // Fp2 mul imag part end + let t157 = circuit_mul(t126, t128); // Fp2 mul start + let t158 = circuit_mul(t127, t129); + let t159 = circuit_sub(t157, t158); // Fp2 mul real part end + let t160 = circuit_mul(t126, t129); + let t161 = circuit_mul(t127, t128); + let t162 = circuit_add(t160, t161); // Fp2 mul imag part end + let t163 = circuit_add(t159, t162); + let t164 = circuit_mul(t163, in0); + let t165 = circuit_mul(t159, in1); + let t166 = circuit_sub(t165, t162); + let t167 = circuit_sub(t164, t165); + let t168 = circuit_sub(t167, t162); + let t169 = circuit_sub(in2, t166); // Fp2 neg coeff 0/1 + let t170 = circuit_sub(in2, t168); // Fp2 neg coeff 1/1 + let t171 = circuit_add(t169, t132); // Fp2 add coeff 0/1 + let t172 = circuit_add(t170, t134); // Fp2 add coeff 1/1 + let t173 = circuit_add(t142, t144); + let t174 = circuit_mul(t173, in0); + let t175 = circuit_mul(t142, in1); + let t176 = circuit_sub(t175, t144); + let t177 = circuit_sub(t174, t175); + let t178 = circuit_sub(t177, t144); + let t179 = circuit_sub(t176, t147); // Fp2 sub coeff 0/1 + let t180 = circuit_sub(t178, t150); // Fp2 sub coeff 1/1 + let t181 = circuit_sub(t137, t153); // Fp2 sub coeff 0/1 + let t182 = circuit_sub(t139, t156); // Fp2 sub coeff 1/1 + let t183 = circuit_mul(t124, t171); // Fp2 mul start + let t184 = circuit_mul(t125, t172); + let t185 = circuit_sub(t183, t184); // Fp2 mul real part end + let t186 = circuit_mul(t124, t172); + let t187 = circuit_mul(t125, t171); + let t188 = circuit_add(t186, t187); // Fp2 mul imag part end + let t189 = circuit_mul(t128, t179); // Fp2 mul start + let t190 = circuit_mul(t129, t180); + let t191 = circuit_sub(t189, t190); // Fp2 mul real part end + let t192 = circuit_mul(t128, t180); + let t193 = circuit_mul(t129, t179); + let t194 = circuit_add(t192, t193); // Fp2 mul imag part end + let t195 = circuit_mul(t126, t181); // Fp2 mul start + let t196 = circuit_mul(t127, t182); + let t197 = circuit_sub(t195, t196); // Fp2 mul real part end + let t198 = circuit_mul(t126, t182); + let t199 = circuit_mul(t127, t181); + let t200 = circuit_add(t198, t199); // Fp2 mul imag part end + let t201 = circuit_add(t191, t197); // Fp2 add coeff 0/1 + let t202 = circuit_add(t194, t200); // Fp2 add coeff 1/1 + let t203 = circuit_add(t201, t202); + let t204 = circuit_mul(t203, in0); + let t205 = circuit_mul(t201, in1); + let t206 = circuit_sub(t205, t202); + let t207 = circuit_sub(t204, t205); + let t208 = circuit_sub(t207, t202); + let t209 = circuit_add(t185, t206); // Fp2 add coeff 0/1 + let t210 = circuit_add(t188, t208); // Fp2 add coeff 1/1 + let t211 = circuit_mul(t209, t209); // Fp2 Inv start + let t212 = circuit_mul(t210, t210); + let t213 = circuit_add(t211, t212); + let t214 = circuit_inverse(t213); + let t215 = circuit_mul(t209, t214); // Fp2 Inv real part end + let t216 = circuit_mul(t210, t214); + let t217 = circuit_sub(in2, t216); // Fp2 Inv imag part end + let t218 = circuit_mul(t171, t215); // Fp2 mul start + let t219 = circuit_mul(t172, t217); + let t220 = circuit_sub(t218, t219); // Fp2 mul real part end + let t221 = circuit_mul(t171, t217); + let t222 = circuit_mul(t172, t215); + let t223 = circuit_add(t221, t222); // Fp2 mul imag part end + let t224 = circuit_mul(t179, t215); // Fp2 mul start + let t225 = circuit_mul(t180, t217); + let t226 = circuit_sub(t224, t225); // Fp2 mul real part end + let t227 = circuit_mul(t179, t217); + let t228 = circuit_mul(t180, t215); + let t229 = circuit_add(t227, t228); // Fp2 mul imag part end + let t230 = circuit_mul(t181, t215); // Fp2 mul start + let t231 = circuit_mul(t182, t217); + let t232 = circuit_sub(t230, t231); // Fp2 mul real part end + let t233 = circuit_mul(t181, t217); + let t234 = circuit_mul(t182, t215); + let t235 = circuit_add(t233, t234); // Fp2 mul imag part end + let t236 = circuit_mul(in3, t220); // Fp2 mul start + let t237 = circuit_mul(in4, t223); + let t238 = circuit_sub(t236, t237); // Fp2 mul real part end + let t239 = circuit_mul(in3, t223); + let t240 = circuit_mul(in4, t220); + let t241 = circuit_add(t239, t240); // Fp2 mul imag part end + let t242 = circuit_mul(in5, t226); // Fp2 mul start + let t243 = circuit_mul(in6, t229); + let t244 = circuit_sub(t242, t243); // Fp2 mul real part end + let t245 = circuit_mul(in5, t229); + let t246 = circuit_mul(in6, t226); + let t247 = circuit_add(t245, t246); // Fp2 mul imag part end + let t248 = circuit_mul(in7, t232); // Fp2 mul start + let t249 = circuit_mul(in8, t235); + let t250 = circuit_sub(t248, t249); // Fp2 mul real part end + let t251 = circuit_mul(in7, t235); + let t252 = circuit_mul(in8, t232); + let t253 = circuit_add(t251, t252); // Fp2 mul imag part end + let t254 = circuit_add(in5, in7); // Fp2 add coeff 0/1 + let t255 = circuit_add(in6, in8); // Fp2 add coeff 1/1 + let t256 = circuit_add(t226, t232); // Fp2 add coeff 0/1 + let t257 = circuit_add(t229, t235); // Fp2 add coeff 1/1 + let t258 = circuit_mul(t254, t256); // Fp2 mul start + let t259 = circuit_mul(t255, t257); + let t260 = circuit_sub(t258, t259); // Fp2 mul real part end + let t261 = circuit_mul(t254, t257); + let t262 = circuit_mul(t255, t256); + let t263 = circuit_add(t261, t262); // Fp2 mul imag part end + let t264 = circuit_sub(t260, t244); // Fp2 sub coeff 0/1 + let t265 = circuit_sub(t263, t247); // Fp2 sub coeff 1/1 + let t266 = circuit_sub(t264, t250); // Fp2 sub coeff 0/1 + let t267 = circuit_sub(t265, t253); // Fp2 sub coeff 1/1 + let t268 = circuit_add(t266, t267); + let t269 = circuit_mul(t268, in0); + let t270 = circuit_mul(t266, in1); + let t271 = circuit_sub(t270, t267); + let t272 = circuit_sub(t269, t270); + let t273 = circuit_sub(t272, t267); + let t274 = circuit_add(t271, t238); // Fp2 add coeff 0/1 + let t275 = circuit_add(t273, t241); // Fp2 add coeff 1/1 + let t276 = circuit_add(in3, in5); // Fp2 add coeff 0/1 + let t277 = circuit_add(in4, in6); // Fp2 add coeff 1/1 + let t278 = circuit_add(t220, t226); // Fp2 add coeff 0/1 + let t279 = circuit_add(t223, t229); // Fp2 add coeff 1/1 + let t280 = circuit_mul(t276, t278); // Fp2 mul start + let t281 = circuit_mul(t277, t279); + let t282 = circuit_sub(t280, t281); // Fp2 mul real part end + let t283 = circuit_mul(t276, t279); + let t284 = circuit_mul(t277, t278); + let t285 = circuit_add(t283, t284); // Fp2 mul imag part end + let t286 = circuit_sub(t282, t238); // Fp2 sub coeff 0/1 + let t287 = circuit_sub(t285, t241); // Fp2 sub coeff 1/1 + let t288 = circuit_sub(t286, t244); // Fp2 sub coeff 0/1 + let t289 = circuit_sub(t287, t247); // Fp2 sub coeff 1/1 + let t290 = circuit_add(t250, t253); + let t291 = circuit_mul(t290, in0); + let t292 = circuit_mul(t250, in1); + let t293 = circuit_sub(t292, t253); + let t294 = circuit_sub(t291, t292); + let t295 = circuit_sub(t294, t253); + let t296 = circuit_add(t288, t293); // Fp2 add coeff 0/1 + let t297 = circuit_add(t289, t295); // Fp2 add coeff 1/1 + let t298 = circuit_add(in3, in7); // Fp2 add coeff 0/1 + let t299 = circuit_add(in4, in8); // Fp2 add coeff 1/1 + let t300 = circuit_add(t220, t232); // Fp2 add coeff 0/1 + let t301 = circuit_add(t223, t235); // Fp2 add coeff 1/1 + let t302 = circuit_mul(t300, t298); // Fp2 mul start + let t303 = circuit_mul(t301, t299); + let t304 = circuit_sub(t302, t303); // Fp2 mul real part end + let t305 = circuit_mul(t300, t299); + let t306 = circuit_mul(t301, t298); + let t307 = circuit_add(t305, t306); // Fp2 mul imag part end + let t308 = circuit_sub(t304, t238); // Fp2 sub coeff 0/1 + let t309 = circuit_sub(t307, t241); // Fp2 sub coeff 1/1 + let t310 = circuit_sub(t308, t250); // Fp2 sub coeff 0/1 + let t311 = circuit_sub(t309, t253); // Fp2 sub coeff 1/1 + let t312 = circuit_add(t310, t244); // Fp2 add coeff 0/1 + let t313 = circuit_add(t311, t247); // Fp2 add coeff 1/1 + let t314 = circuit_mul(in9, t220); // Fp2 mul start + let t315 = circuit_mul(in10, t223); + let t316 = circuit_sub(t314, t315); // Fp2 mul real part end + let t317 = circuit_mul(in9, t223); + let t318 = circuit_mul(in10, t220); + let t319 = circuit_add(t317, t318); // Fp2 mul imag part end + let t320 = circuit_mul(in11, t226); // Fp2 mul start + let t321 = circuit_mul(in12, t229); + let t322 = circuit_sub(t320, t321); // Fp2 mul real part end + let t323 = circuit_mul(in11, t229); + let t324 = circuit_mul(in12, t226); + let t325 = circuit_add(t323, t324); // Fp2 mul imag part end + let t326 = circuit_mul(in13, t232); // Fp2 mul start + let t327 = circuit_mul(in14, t235); + let t328 = circuit_sub(t326, t327); // Fp2 mul real part end + let t329 = circuit_mul(in13, t235); + let t330 = circuit_mul(in14, t232); + let t331 = circuit_add(t329, t330); // Fp2 mul imag part end + let t332 = circuit_add(in11, in13); // Fp2 add coeff 0/1 + let t333 = circuit_add(in12, in14); // Fp2 add coeff 1/1 + let t334 = circuit_add(t226, t232); // Fp2 add coeff 0/1 + let t335 = circuit_add(t229, t235); // Fp2 add coeff 1/1 + let t336 = circuit_mul(t332, t334); // Fp2 mul start + let t337 = circuit_mul(t333, t335); + let t338 = circuit_sub(t336, t337); // Fp2 mul real part end + let t339 = circuit_mul(t332, t335); + let t340 = circuit_mul(t333, t334); + let t341 = circuit_add(t339, t340); // Fp2 mul imag part end + let t342 = circuit_sub(t338, t322); // Fp2 sub coeff 0/1 + let t343 = circuit_sub(t341, t325); // Fp2 sub coeff 1/1 + let t344 = circuit_sub(t342, t328); // Fp2 sub coeff 0/1 + let t345 = circuit_sub(t343, t331); // Fp2 sub coeff 1/1 + let t346 = circuit_add(t344, t345); + let t347 = circuit_mul(t346, in0); + let t348 = circuit_mul(t344, in1); + let t349 = circuit_sub(t348, t345); + let t350 = circuit_sub(t347, t348); + let t351 = circuit_sub(t350, t345); + let t352 = circuit_add(t349, t316); // Fp2 add coeff 0/1 + let t353 = circuit_add(t351, t319); // Fp2 add coeff 1/1 + let t354 = circuit_add(in9, in11); // Fp2 add coeff 0/1 + let t355 = circuit_add(in10, in12); // Fp2 add coeff 1/1 + let t356 = circuit_add(t220, t226); // Fp2 add coeff 0/1 + let t357 = circuit_add(t223, t229); // Fp2 add coeff 1/1 + let t358 = circuit_mul(t354, t356); // Fp2 mul start + let t359 = circuit_mul(t355, t357); + let t360 = circuit_sub(t358, t359); // Fp2 mul real part end + let t361 = circuit_mul(t354, t357); + let t362 = circuit_mul(t355, t356); + let t363 = circuit_add(t361, t362); // Fp2 mul imag part end + let t364 = circuit_sub(t360, t316); // Fp2 sub coeff 0/1 + let t365 = circuit_sub(t363, t319); // Fp2 sub coeff 1/1 + let t366 = circuit_sub(t364, t322); // Fp2 sub coeff 0/1 + let t367 = circuit_sub(t365, t325); // Fp2 sub coeff 1/1 + let t368 = circuit_add(t328, t331); + let t369 = circuit_mul(t368, in0); + let t370 = circuit_mul(t328, in1); + let t371 = circuit_sub(t370, t331); + let t372 = circuit_sub(t369, t370); + let t373 = circuit_sub(t372, t331); + let t374 = circuit_add(t366, t371); // Fp2 add coeff 0/1 + let t375 = circuit_add(t367, t373); // Fp2 add coeff 1/1 + let t376 = circuit_add(in9, in13); // Fp2 add coeff 0/1 + let t377 = circuit_add(in10, in14); // Fp2 add coeff 1/1 + let t378 = circuit_add(t220, t232); // Fp2 add coeff 0/1 + let t379 = circuit_add(t223, t235); // Fp2 add coeff 1/1 + let t380 = circuit_mul(t378, t376); // Fp2 mul start + let t381 = circuit_mul(t379, t377); + let t382 = circuit_sub(t380, t381); // Fp2 mul real part end + let t383 = circuit_mul(t378, t377); + let t384 = circuit_mul(t379, t376); + let t385 = circuit_add(t383, t384); // Fp2 mul imag part end + let t386 = circuit_sub(t382, t316); // Fp2 sub coeff 0/1 + let t387 = circuit_sub(t385, t319); // Fp2 sub coeff 1/1 + let t388 = circuit_sub(t386, t328); // Fp2 sub coeff 0/1 + let t389 = circuit_sub(t387, t331); // Fp2 sub coeff 1/1 + let t390 = circuit_add(t388, t322); // Fp2 add coeff 0/1 + let t391 = circuit_add(t389, t325); // Fp2 add coeff 1/1 + let t392 = circuit_sub(in2, t352); // Fp6 neg coeff 0/5 + let t393 = circuit_sub(in2, t353); // Fp6 neg coeff 1/5 + let t394 = circuit_sub(in2, t374); // Fp6 neg coeff 2/5 + let t395 = circuit_sub(in2, t375); // Fp6 neg coeff 3/5 + let t396 = circuit_sub(in2, t390); // Fp6 neg coeff 4/5 + let t397 = circuit_sub(in2, t391); // Fp6 neg coeff 5/5 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = ( + t274, t275, t296, t297, t312, t313, t392, t393, t394, t395, t396, t397, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0xa, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x9, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in2 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(M.c0b0a0); // in3 + circuit_inputs = circuit_inputs.next_2(M.c0b0a1); // in4 + circuit_inputs = circuit_inputs.next_2(M.c0b1a0); // in5 + circuit_inputs = circuit_inputs.next_2(M.c0b1a1); // in6 + circuit_inputs = circuit_inputs.next_2(M.c0b2a0); // in7 + circuit_inputs = circuit_inputs.next_2(M.c0b2a1); // in8 + circuit_inputs = circuit_inputs.next_2(M.c1b0a0); // in9 + circuit_inputs = circuit_inputs.next_2(M.c1b0a1); // in10 + circuit_inputs = circuit_inputs.next_2(M.c1b1a0); // in11 + circuit_inputs = circuit_inputs.next_2(M.c1b1a1); // in12 + circuit_inputs = circuit_inputs.next_2(M.c1b2a0); // in13 + circuit_inputs = circuit_inputs.next_2(M.c1b2a1); // in14 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t274), + c0b0a1: outputs.get_output(t275), + c0b1a0: outputs.get_output(t296), + c0b1a1: outputs.get_output(t297), + c0b2a0: outputs.get_output(t312), + c0b2a1: outputs.get_output(t313), + c1b0a0: outputs.get_output(t392), + c1b0a1: outputs.get_output(t393), + c1b1a0: outputs.get_output(t394), + c1b1a1: outputs.get_output(t395), + c1b2a0: outputs.get_output(t396), + c1b2a1: outputs.get_output(t397), + }; + return (res,); +} +#[inline(always)] +fn run_BN254_E12T_MUL_circuit(X: E12T, Y: E12T) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0xa + let in1 = CE::> {}; // 0x9 + + // INPUT stack + let (in2, in3, in4) = (CE::> {}, CE::> {}, CE::> {}); + let (in5, in6, in7) = (CE::> {}, CE::> {}, CE::> {}); + let (in8, in9, in10) = (CE::> {}, CE::> {}, CE::> {}); + let (in11, in12, in13) = (CE::> {}, CE::> {}, CE::> {}); + let (in14, in15, in16) = (CE::> {}, CE::> {}, CE::> {}); + let (in17, in18, in19) = (CE::> {}, CE::> {}, CE::> {}); + let (in20, in21, in22) = (CE::> {}, CE::> {}, CE::> {}); + let (in23, in24, in25) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_add(in2, in8); // Fp6 add coeff 0/5 + let t1 = circuit_add(in3, in9); // Fp6 add coeff 1/5 + let t2 = circuit_add(in4, in10); // Fp6 add coeff 2/5 + let t3 = circuit_add(in5, in11); // Fp6 add coeff 3/5 + let t4 = circuit_add(in6, in12); // Fp6 add coeff 4/5 + let t5 = circuit_add(in7, in13); // Fp6 add coeff 5/5 + let t6 = circuit_add(in14, in20); // Fp6 add coeff 0/5 + let t7 = circuit_add(in15, in21); // Fp6 add coeff 1/5 + let t8 = circuit_add(in16, in22); // Fp6 add coeff 2/5 + let t9 = circuit_add(in17, in23); // Fp6 add coeff 3/5 + let t10 = circuit_add(in18, in24); // Fp6 add coeff 4/5 + let t11 = circuit_add(in19, in25); // Fp6 add coeff 5/5 + let t12 = circuit_mul(t0, t6); // Fp2 mul start + let t13 = circuit_mul(t1, t7); + let t14 = circuit_sub(t12, t13); // Fp2 mul real part end + let t15 = circuit_mul(t0, t7); + let t16 = circuit_mul(t1, t6); + let t17 = circuit_add(t15, t16); // Fp2 mul imag part end + let t18 = circuit_mul(t2, t8); // Fp2 mul start + let t19 = circuit_mul(t3, t9); + let t20 = circuit_sub(t18, t19); // Fp2 mul real part end + let t21 = circuit_mul(t2, t9); + let t22 = circuit_mul(t3, t8); + let t23 = circuit_add(t21, t22); // Fp2 mul imag part end + let t24 = circuit_mul(t4, t10); // Fp2 mul start + let t25 = circuit_mul(t5, t11); + let t26 = circuit_sub(t24, t25); // Fp2 mul real part end + let t27 = circuit_mul(t4, t11); + let t28 = circuit_mul(t5, t10); + let t29 = circuit_add(t27, t28); // Fp2 mul imag part end + let t30 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t31 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t32 = circuit_add(t8, t10); // Fp2 add coeff 0/1 + let t33 = circuit_add(t9, t11); // Fp2 add coeff 1/1 + let t34 = circuit_mul(t30, t32); // Fp2 mul start + let t35 = circuit_mul(t31, t33); + let t36 = circuit_sub(t34, t35); // Fp2 mul real part end + let t37 = circuit_mul(t30, t33); + let t38 = circuit_mul(t31, t32); + let t39 = circuit_add(t37, t38); // Fp2 mul imag part end + let t40 = circuit_sub(t36, t20); // Fp2 sub coeff 0/1 + let t41 = circuit_sub(t39, t23); // Fp2 sub coeff 1/1 + let t42 = circuit_sub(t40, t26); // Fp2 sub coeff 0/1 + let t43 = circuit_sub(t41, t29); // Fp2 sub coeff 1/1 + let t44 = circuit_add(t42, t43); + let t45 = circuit_mul(t44, in0); + let t46 = circuit_mul(t42, in1); + let t47 = circuit_sub(t46, t43); + let t48 = circuit_sub(t45, t46); + let t49 = circuit_sub(t48, t43); + let t50 = circuit_add(t47, t14); // Fp2 add coeff 0/1 + let t51 = circuit_add(t49, t17); // Fp2 add coeff 1/1 + let t52 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t53 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t54 = circuit_add(t6, t8); // Fp2 add coeff 0/1 + let t55 = circuit_add(t7, t9); // Fp2 add coeff 1/1 + let t56 = circuit_mul(t52, t54); // Fp2 mul start + let t57 = circuit_mul(t53, t55); + let t58 = circuit_sub(t56, t57); // Fp2 mul real part end + let t59 = circuit_mul(t52, t55); + let t60 = circuit_mul(t53, t54); + let t61 = circuit_add(t59, t60); // Fp2 mul imag part end + let t62 = circuit_sub(t58, t14); // Fp2 sub coeff 0/1 + let t63 = circuit_sub(t61, t17); // Fp2 sub coeff 1/1 + let t64 = circuit_sub(t62, t20); // Fp2 sub coeff 0/1 + let t65 = circuit_sub(t63, t23); // Fp2 sub coeff 1/1 + let t66 = circuit_add(t26, t29); + let t67 = circuit_mul(t66, in0); + let t68 = circuit_mul(t26, in1); + let t69 = circuit_sub(t68, t29); + let t70 = circuit_sub(t67, t68); + let t71 = circuit_sub(t70, t29); + let t72 = circuit_add(t64, t69); // Fp2 add coeff 0/1 + let t73 = circuit_add(t65, t71); // Fp2 add coeff 1/1 + let t74 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t75 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t76 = circuit_add(t6, t10); // Fp2 add coeff 0/1 + let t77 = circuit_add(t7, t11); // Fp2 add coeff 1/1 + let t78 = circuit_mul(t76, t74); // Fp2 mul start + let t79 = circuit_mul(t77, t75); + let t80 = circuit_sub(t78, t79); // Fp2 mul real part end + let t81 = circuit_mul(t76, t75); + let t82 = circuit_mul(t77, t74); + let t83 = circuit_add(t81, t82); // Fp2 mul imag part end + let t84 = circuit_sub(t80, t14); // Fp2 sub coeff 0/1 + let t85 = circuit_sub(t83, t17); // Fp2 sub coeff 1/1 + let t86 = circuit_sub(t84, t26); // Fp2 sub coeff 0/1 + let t87 = circuit_sub(t85, t29); // Fp2 sub coeff 1/1 + let t88 = circuit_add(t86, t20); // Fp2 add coeff 0/1 + let t89 = circuit_add(t87, t23); // Fp2 add coeff 1/1 + let t90 = circuit_mul(in2, in14); // Fp2 mul start + let t91 = circuit_mul(in3, in15); + let t92 = circuit_sub(t90, t91); // Fp2 mul real part end + let t93 = circuit_mul(in2, in15); + let t94 = circuit_mul(in3, in14); + let t95 = circuit_add(t93, t94); // Fp2 mul imag part end + let t96 = circuit_mul(in4, in16); // Fp2 mul start + let t97 = circuit_mul(in5, in17); + let t98 = circuit_sub(t96, t97); // Fp2 mul real part end + let t99 = circuit_mul(in4, in17); + let t100 = circuit_mul(in5, in16); + let t101 = circuit_add(t99, t100); // Fp2 mul imag part end + let t102 = circuit_mul(in6, in18); // Fp2 mul start + let t103 = circuit_mul(in7, in19); + let t104 = circuit_sub(t102, t103); // Fp2 mul real part end + let t105 = circuit_mul(in6, in19); + let t106 = circuit_mul(in7, in18); + let t107 = circuit_add(t105, t106); // Fp2 mul imag part end + let t108 = circuit_add(in4, in6); // Fp2 add coeff 0/1 + let t109 = circuit_add(in5, in7); // Fp2 add coeff 1/1 + let t110 = circuit_add(in16, in18); // Fp2 add coeff 0/1 + let t111 = circuit_add(in17, in19); // Fp2 add coeff 1/1 + let t112 = circuit_mul(t108, t110); // Fp2 mul start + let t113 = circuit_mul(t109, t111); + let t114 = circuit_sub(t112, t113); // Fp2 mul real part end + let t115 = circuit_mul(t108, t111); + let t116 = circuit_mul(t109, t110); + let t117 = circuit_add(t115, t116); // Fp2 mul imag part end + let t118 = circuit_sub(t114, t98); // Fp2 sub coeff 0/1 + let t119 = circuit_sub(t117, t101); // Fp2 sub coeff 1/1 + let t120 = circuit_sub(t118, t104); // Fp2 sub coeff 0/1 + let t121 = circuit_sub(t119, t107); // Fp2 sub coeff 1/1 + let t122 = circuit_add(t120, t121); + let t123 = circuit_mul(t122, in0); + let t124 = circuit_mul(t120, in1); + let t125 = circuit_sub(t124, t121); + let t126 = circuit_sub(t123, t124); + let t127 = circuit_sub(t126, t121); + let t128 = circuit_add(t125, t92); // Fp2 add coeff 0/1 + let t129 = circuit_add(t127, t95); // Fp2 add coeff 1/1 + let t130 = circuit_add(in2, in4); // Fp2 add coeff 0/1 + let t131 = circuit_add(in3, in5); // Fp2 add coeff 1/1 + let t132 = circuit_add(in14, in16); // Fp2 add coeff 0/1 + let t133 = circuit_add(in15, in17); // Fp2 add coeff 1/1 + let t134 = circuit_mul(t130, t132); // Fp2 mul start + let t135 = circuit_mul(t131, t133); + let t136 = circuit_sub(t134, t135); // Fp2 mul real part end + let t137 = circuit_mul(t130, t133); + let t138 = circuit_mul(t131, t132); + let t139 = circuit_add(t137, t138); // Fp2 mul imag part end + let t140 = circuit_sub(t136, t92); // Fp2 sub coeff 0/1 + let t141 = circuit_sub(t139, t95); // Fp2 sub coeff 1/1 + let t142 = circuit_sub(t140, t98); // Fp2 sub coeff 0/1 + let t143 = circuit_sub(t141, t101); // Fp2 sub coeff 1/1 + let t144 = circuit_add(t104, t107); + let t145 = circuit_mul(t144, in0); + let t146 = circuit_mul(t104, in1); + let t147 = circuit_sub(t146, t107); + let t148 = circuit_sub(t145, t146); + let t149 = circuit_sub(t148, t107); + let t150 = circuit_add(t142, t147); // Fp2 add coeff 0/1 + let t151 = circuit_add(t143, t149); // Fp2 add coeff 1/1 + let t152 = circuit_add(in2, in6); // Fp2 add coeff 0/1 + let t153 = circuit_add(in3, in7); // Fp2 add coeff 1/1 + let t154 = circuit_add(in14, in18); // Fp2 add coeff 0/1 + let t155 = circuit_add(in15, in19); // Fp2 add coeff 1/1 + let t156 = circuit_mul(t154, t152); // Fp2 mul start + let t157 = circuit_mul(t155, t153); + let t158 = circuit_sub(t156, t157); // Fp2 mul real part end + let t159 = circuit_mul(t154, t153); + let t160 = circuit_mul(t155, t152); + let t161 = circuit_add(t159, t160); // Fp2 mul imag part end + let t162 = circuit_sub(t158, t92); // Fp2 sub coeff 0/1 + let t163 = circuit_sub(t161, t95); // Fp2 sub coeff 1/1 + let t164 = circuit_sub(t162, t104); // Fp2 sub coeff 0/1 + let t165 = circuit_sub(t163, t107); // Fp2 sub coeff 1/1 + let t166 = circuit_add(t164, t98); // Fp2 add coeff 0/1 + let t167 = circuit_add(t165, t101); // Fp2 add coeff 1/1 + let t168 = circuit_mul(in8, in20); // Fp2 mul start + let t169 = circuit_mul(in9, in21); + let t170 = circuit_sub(t168, t169); // Fp2 mul real part end + let t171 = circuit_mul(in8, in21); + let t172 = circuit_mul(in9, in20); + let t173 = circuit_add(t171, t172); // Fp2 mul imag part end + let t174 = circuit_mul(in10, in22); // Fp2 mul start + let t175 = circuit_mul(in11, in23); + let t176 = circuit_sub(t174, t175); // Fp2 mul real part end + let t177 = circuit_mul(in10, in23); + let t178 = circuit_mul(in11, in22); + let t179 = circuit_add(t177, t178); // Fp2 mul imag part end + let t180 = circuit_mul(in12, in24); // Fp2 mul start + let t181 = circuit_mul(in13, in25); + let t182 = circuit_sub(t180, t181); // Fp2 mul real part end + let t183 = circuit_mul(in12, in25); + let t184 = circuit_mul(in13, in24); + let t185 = circuit_add(t183, t184); // Fp2 mul imag part end + let t186 = circuit_add(in10, in12); // Fp2 add coeff 0/1 + let t187 = circuit_add(in11, in13); // Fp2 add coeff 1/1 + let t188 = circuit_add(in22, in24); // Fp2 add coeff 0/1 + let t189 = circuit_add(in23, in25); // Fp2 add coeff 1/1 + let t190 = circuit_mul(t186, t188); // Fp2 mul start + let t191 = circuit_mul(t187, t189); + let t192 = circuit_sub(t190, t191); // Fp2 mul real part end + let t193 = circuit_mul(t186, t189); + let t194 = circuit_mul(t187, t188); + let t195 = circuit_add(t193, t194); // Fp2 mul imag part end + let t196 = circuit_sub(t192, t176); // Fp2 sub coeff 0/1 + let t197 = circuit_sub(t195, t179); // Fp2 sub coeff 1/1 + let t198 = circuit_sub(t196, t182); // Fp2 sub coeff 0/1 + let t199 = circuit_sub(t197, t185); // Fp2 sub coeff 1/1 + let t200 = circuit_add(t198, t199); + let t201 = circuit_mul(t200, in0); + let t202 = circuit_mul(t198, in1); + let t203 = circuit_sub(t202, t199); + let t204 = circuit_sub(t201, t202); + let t205 = circuit_sub(t204, t199); + let t206 = circuit_add(t203, t170); // Fp2 add coeff 0/1 + let t207 = circuit_add(t205, t173); // Fp2 add coeff 1/1 + let t208 = circuit_add(in8, in10); // Fp2 add coeff 0/1 + let t209 = circuit_add(in9, in11); // Fp2 add coeff 1/1 + let t210 = circuit_add(in20, in22); // Fp2 add coeff 0/1 + let t211 = circuit_add(in21, in23); // Fp2 add coeff 1/1 + let t212 = circuit_mul(t208, t210); // Fp2 mul start + let t213 = circuit_mul(t209, t211); + let t214 = circuit_sub(t212, t213); // Fp2 mul real part end + let t215 = circuit_mul(t208, t211); + let t216 = circuit_mul(t209, t210); + let t217 = circuit_add(t215, t216); // Fp2 mul imag part end + let t218 = circuit_sub(t214, t170); // Fp2 sub coeff 0/1 + let t219 = circuit_sub(t217, t173); // Fp2 sub coeff 1/1 + let t220 = circuit_sub(t218, t176); // Fp2 sub coeff 0/1 + let t221 = circuit_sub(t219, t179); // Fp2 sub coeff 1/1 + let t222 = circuit_add(t182, t185); + let t223 = circuit_mul(t222, in0); + let t224 = circuit_mul(t182, in1); + let t225 = circuit_sub(t224, t185); + let t226 = circuit_sub(t223, t224); + let t227 = circuit_sub(t226, t185); + let t228 = circuit_add(t220, t225); // Fp2 add coeff 0/1 + let t229 = circuit_add(t221, t227); // Fp2 add coeff 1/1 + let t230 = circuit_add(in8, in12); // Fp2 add coeff 0/1 + let t231 = circuit_add(in9, in13); // Fp2 add coeff 1/1 + let t232 = circuit_add(in20, in24); // Fp2 add coeff 0/1 + let t233 = circuit_add(in21, in25); // Fp2 add coeff 1/1 + let t234 = circuit_mul(t232, t230); // Fp2 mul start + let t235 = circuit_mul(t233, t231); + let t236 = circuit_sub(t234, t235); // Fp2 mul real part end + let t237 = circuit_mul(t232, t231); + let t238 = circuit_mul(t233, t230); + let t239 = circuit_add(t237, t238); // Fp2 mul imag part end + let t240 = circuit_sub(t236, t170); // Fp2 sub coeff 0/1 + let t241 = circuit_sub(t239, t173); // Fp2 sub coeff 1/1 + let t242 = circuit_sub(t240, t182); // Fp2 sub coeff 0/1 + let t243 = circuit_sub(t241, t185); // Fp2 sub coeff 1/1 + let t244 = circuit_add(t242, t176); // Fp2 add coeff 0/1 + let t245 = circuit_add(t243, t179); // Fp2 add coeff 1/1 + let t246 = circuit_sub(t50, t128); // Fp6 sub coeff 0/5 + let t247 = circuit_sub(t51, t129); // Fp6 sub coeff 1/5 + let t248 = circuit_sub(t72, t150); // Fp6 sub coeff 2/5 + let t249 = circuit_sub(t73, t151); // Fp6 sub coeff 3/5 + let t250 = circuit_sub(t88, t166); // Fp6 sub coeff 4/5 + let t251 = circuit_sub(t89, t167); // Fp6 sub coeff 5/5 + let t252 = circuit_sub(t246, t206); // Fp6 sub coeff 0/5 + let t253 = circuit_sub(t247, t207); // Fp6 sub coeff 1/5 + let t254 = circuit_sub(t248, t228); // Fp6 sub coeff 2/5 + let t255 = circuit_sub(t249, t229); // Fp6 sub coeff 3/5 + let t256 = circuit_sub(t250, t244); // Fp6 sub coeff 4/5 + let t257 = circuit_sub(t251, t245); // Fp6 sub coeff 5/5 + let t258 = circuit_add(t244, t245); + let t259 = circuit_mul(t258, in0); + let t260 = circuit_mul(t244, in1); + let t261 = circuit_sub(t260, t245); + let t262 = circuit_sub(t259, t260); + let t263 = circuit_sub(t262, t245); + let t264 = circuit_add(t261, t128); // Fp6 add coeff 0/5 + let t265 = circuit_add(t263, t129); // Fp6 add coeff 1/5 + let t266 = circuit_add(t206, t150); // Fp6 add coeff 2/5 + let t267 = circuit_add(t207, t151); // Fp6 add coeff 3/5 + let t268 = circuit_add(t228, t166); // Fp6 add coeff 4/5 + let t269 = circuit_add(t229, t167); // Fp6 add coeff 5/5 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = ( + t264, t265, t266, t267, t268, t269, t252, t253, t254, t255, t256, t257, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0xa, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x9, 0x0, 0x0, 0x0]); // in1 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(X.c0b0a0); // in2 + circuit_inputs = circuit_inputs.next_2(X.c0b0a1); // in3 + circuit_inputs = circuit_inputs.next_2(X.c0b1a0); // in4 + circuit_inputs = circuit_inputs.next_2(X.c0b1a1); // in5 + circuit_inputs = circuit_inputs.next_2(X.c0b2a0); // in6 + circuit_inputs = circuit_inputs.next_2(X.c0b2a1); // in7 + circuit_inputs = circuit_inputs.next_2(X.c1b0a0); // in8 + circuit_inputs = circuit_inputs.next_2(X.c1b0a1); // in9 + circuit_inputs = circuit_inputs.next_2(X.c1b1a0); // in10 + circuit_inputs = circuit_inputs.next_2(X.c1b1a1); // in11 + circuit_inputs = circuit_inputs.next_2(X.c1b2a0); // in12 + circuit_inputs = circuit_inputs.next_2(X.c1b2a1); // in13 + circuit_inputs = circuit_inputs.next_2(Y.c0b0a0); // in14 + circuit_inputs = circuit_inputs.next_2(Y.c0b0a1); // in15 + circuit_inputs = circuit_inputs.next_2(Y.c0b1a0); // in16 + circuit_inputs = circuit_inputs.next_2(Y.c0b1a1); // in17 + circuit_inputs = circuit_inputs.next_2(Y.c0b2a0); // in18 + circuit_inputs = circuit_inputs.next_2(Y.c0b2a1); // in19 + circuit_inputs = circuit_inputs.next_2(Y.c1b0a0); // in20 + circuit_inputs = circuit_inputs.next_2(Y.c1b0a1); // in21 + circuit_inputs = circuit_inputs.next_2(Y.c1b1a0); // in22 + circuit_inputs = circuit_inputs.next_2(Y.c1b1a1); // in23 + circuit_inputs = circuit_inputs.next_2(Y.c1b2a0); // in24 + circuit_inputs = circuit_inputs.next_2(Y.c1b2a1); // in25 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let res: E12T = E12T { + c0b0a0: outputs.get_output(t264), + c0b0a1: outputs.get_output(t265), + c0b1a0: outputs.get_output(t266), + c0b1a1: outputs.get_output(t267), + c0b2a0: outputs.get_output(t268), + c0b2a1: outputs.get_output(t269), + c1b0a0: outputs.get_output(t252), + c1b0a1: outputs.get_output(t253), + c1b1a0: outputs.get_output(t254), + c1b1a1: outputs.get_output(t255), + c1b2a0: outputs.get_output(t256), + c1b2a1: outputs.get_output(t257), + }; + return (res,); +} +#[inline(always)] +fn run_BN254_TOWER_MILLER_BIT0_1P_circuit( + yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point, M_i: E12T +) -> (G2Point, E12T) { + // CONSTANT stack + let in0 = CE::> {}; // 0xa + let in1 = CE::> {}; // 0x9 + let in2 = CE::> {}; // 0x0 + let in3 = CE::> {}; // 0x3 + let in4 = CE::> {}; // 0x6 + let in5 = CE::> {}; // 0x1 + + // INPUT stack + let (in6, in7, in8) = (CE::> {}, CE::> {}, CE::> {}); + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let (in15, in16, in17) = (CE::> {}, CE::> {}, CE::> {}); + let (in18, in19, in20) = (CE::> {}, CE::> {}, CE::> {}); + let (in21, in22, in23) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in12, in18); // Fp6 sub coeff 0/5 + let t1 = circuit_sub(in13, in19); // Fp6 sub coeff 1/5 + let t2 = circuit_sub(in14, in20); // Fp6 sub coeff 2/5 + let t3 = circuit_sub(in15, in21); // Fp6 sub coeff 3/5 + let t4 = circuit_sub(in16, in22); // Fp6 sub coeff 4/5 + let t5 = circuit_sub(in17, in23); // Fp6 sub coeff 5/5 + let t6 = circuit_add(in22, in23); + let t7 = circuit_mul(t6, in0); + let t8 = circuit_mul(in22, in1); + let t9 = circuit_sub(t8, in23); + let t10 = circuit_sub(t7, t8); + let t11 = circuit_sub(t10, in23); + let t12 = circuit_sub(in2, t9); // Fp6 neg coeff 0/5 + let t13 = circuit_sub(in2, t11); // Fp6 neg coeff 1/5 + let t14 = circuit_sub(in2, in18); // Fp6 neg coeff 2/5 + let t15 = circuit_sub(in2, in19); // Fp6 neg coeff 3/5 + let t16 = circuit_sub(in2, in20); // Fp6 neg coeff 4/5 + let t17 = circuit_sub(in2, in21); // Fp6 neg coeff 5/5 + let t18 = circuit_add(in12, t12); // Fp6 add coeff 0/5 + let t19 = circuit_add(in13, t13); // Fp6 add coeff 1/5 + let t20 = circuit_add(in14, t14); // Fp6 add coeff 2/5 + let t21 = circuit_add(in15, t15); // Fp6 add coeff 3/5 + let t22 = circuit_add(in16, t16); // Fp6 add coeff 4/5 + let t23 = circuit_add(in17, t17); // Fp6 add coeff 5/5 + let t24 = circuit_mul(in12, in18); // Fp2 mul start + let t25 = circuit_mul(in13, in19); + let t26 = circuit_sub(t24, t25); // Fp2 mul real part end + let t27 = circuit_mul(in12, in19); + let t28 = circuit_mul(in13, in18); + let t29 = circuit_add(t27, t28); // Fp2 mul imag part end + let t30 = circuit_mul(in14, in20); // Fp2 mul start + let t31 = circuit_mul(in15, in21); + let t32 = circuit_sub(t30, t31); // Fp2 mul real part end + let t33 = circuit_mul(in14, in21); + let t34 = circuit_mul(in15, in20); + let t35 = circuit_add(t33, t34); // Fp2 mul imag part end + let t36 = circuit_mul(in16, in22); // Fp2 mul start + let t37 = circuit_mul(in17, in23); + let t38 = circuit_sub(t36, t37); // Fp2 mul real part end + let t39 = circuit_mul(in16, in23); + let t40 = circuit_mul(in17, in22); + let t41 = circuit_add(t39, t40); // Fp2 mul imag part end + let t42 = circuit_add(in14, in16); // Fp2 add coeff 0/1 + let t43 = circuit_add(in15, in17); // Fp2 add coeff 1/1 + let t44 = circuit_add(in20, in22); // Fp2 add coeff 0/1 + let t45 = circuit_add(in21, in23); // Fp2 add coeff 1/1 + let t46 = circuit_mul(t42, t44); // Fp2 mul start + let t47 = circuit_mul(t43, t45); + let t48 = circuit_sub(t46, t47); // Fp2 mul real part end + let t49 = circuit_mul(t42, t45); + let t50 = circuit_mul(t43, t44); + let t51 = circuit_add(t49, t50); // Fp2 mul imag part end + let t52 = circuit_sub(t48, t32); // Fp2 sub coeff 0/1 + let t53 = circuit_sub(t51, t35); // Fp2 sub coeff 1/1 + let t54 = circuit_sub(t52, t38); // Fp2 sub coeff 0/1 + let t55 = circuit_sub(t53, t41); // Fp2 sub coeff 1/1 + let t56 = circuit_add(t54, t55); + let t57 = circuit_mul(t56, in0); + let t58 = circuit_mul(t54, in1); + let t59 = circuit_sub(t58, t55); + let t60 = circuit_sub(t57, t58); + let t61 = circuit_sub(t60, t55); + let t62 = circuit_add(t59, t26); // Fp2 add coeff 0/1 + let t63 = circuit_add(t61, t29); // Fp2 add coeff 1/1 + let t64 = circuit_add(in12, in14); // Fp2 add coeff 0/1 + let t65 = circuit_add(in13, in15); // Fp2 add coeff 1/1 + let t66 = circuit_add(in18, in20); // Fp2 add coeff 0/1 + let t67 = circuit_add(in19, in21); // Fp2 add coeff 1/1 + let t68 = circuit_mul(t64, t66); // Fp2 mul start + let t69 = circuit_mul(t65, t67); + let t70 = circuit_sub(t68, t69); // Fp2 mul real part end + let t71 = circuit_mul(t64, t67); + let t72 = circuit_mul(t65, t66); + let t73 = circuit_add(t71, t72); // Fp2 mul imag part end + let t74 = circuit_sub(t70, t26); // Fp2 sub coeff 0/1 + let t75 = circuit_sub(t73, t29); // Fp2 sub coeff 1/1 + let t76 = circuit_sub(t74, t32); // Fp2 sub coeff 0/1 + let t77 = circuit_sub(t75, t35); // Fp2 sub coeff 1/1 + let t78 = circuit_add(t38, t41); + let t79 = circuit_mul(t78, in0); + let t80 = circuit_mul(t38, in1); + let t81 = circuit_sub(t80, t41); + let t82 = circuit_sub(t79, t80); + let t83 = circuit_sub(t82, t41); + let t84 = circuit_add(t76, t81); // Fp2 add coeff 0/1 + let t85 = circuit_add(t77, t83); // Fp2 add coeff 1/1 + let t86 = circuit_add(in12, in16); // Fp2 add coeff 0/1 + let t87 = circuit_add(in13, in17); // Fp2 add coeff 1/1 + let t88 = circuit_add(in18, in22); // Fp2 add coeff 0/1 + let t89 = circuit_add(in19, in23); // Fp2 add coeff 1/1 + let t90 = circuit_mul(t88, t86); // Fp2 mul start + let t91 = circuit_mul(t89, t87); + let t92 = circuit_sub(t90, t91); // Fp2 mul real part end + let t93 = circuit_mul(t88, t87); + let t94 = circuit_mul(t89, t86); + let t95 = circuit_add(t93, t94); // Fp2 mul imag part end + let t96 = circuit_sub(t92, t26); // Fp2 sub coeff 0/1 + let t97 = circuit_sub(t95, t29); // Fp2 sub coeff 1/1 + let t98 = circuit_sub(t96, t38); // Fp2 sub coeff 0/1 + let t99 = circuit_sub(t97, t41); // Fp2 sub coeff 1/1 + let t100 = circuit_add(t98, t32); // Fp2 add coeff 0/1 + let t101 = circuit_add(t99, t35); // Fp2 add coeff 1/1 + let t102 = circuit_mul(t0, t18); // Fp2 mul start + let t103 = circuit_mul(t1, t19); + let t104 = circuit_sub(t102, t103); // Fp2 mul real part end + let t105 = circuit_mul(t0, t19); + let t106 = circuit_mul(t1, t18); + let t107 = circuit_add(t105, t106); // Fp2 mul imag part end + let t108 = circuit_mul(t2, t20); // Fp2 mul start + let t109 = circuit_mul(t3, t21); + let t110 = circuit_sub(t108, t109); // Fp2 mul real part end + let t111 = circuit_mul(t2, t21); + let t112 = circuit_mul(t3, t20); + let t113 = circuit_add(t111, t112); // Fp2 mul imag part end + let t114 = circuit_mul(t4, t22); // Fp2 mul start + let t115 = circuit_mul(t5, t23); + let t116 = circuit_sub(t114, t115); // Fp2 mul real part end + let t117 = circuit_mul(t4, t23); + let t118 = circuit_mul(t5, t22); + let t119 = circuit_add(t117, t118); // Fp2 mul imag part end + let t120 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t121 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t122 = circuit_add(t20, t22); // Fp2 add coeff 0/1 + let t123 = circuit_add(t21, t23); // Fp2 add coeff 1/1 + let t124 = circuit_mul(t120, t122); // Fp2 mul start + let t125 = circuit_mul(t121, t123); + let t126 = circuit_sub(t124, t125); // Fp2 mul real part end + let t127 = circuit_mul(t120, t123); + let t128 = circuit_mul(t121, t122); + let t129 = circuit_add(t127, t128); // Fp2 mul imag part end + let t130 = circuit_sub(t126, t110); // Fp2 sub coeff 0/1 + let t131 = circuit_sub(t129, t113); // Fp2 sub coeff 1/1 + let t132 = circuit_sub(t130, t116); // Fp2 sub coeff 0/1 + let t133 = circuit_sub(t131, t119); // Fp2 sub coeff 1/1 + let t134 = circuit_add(t132, t133); + let t135 = circuit_mul(t134, in0); + let t136 = circuit_mul(t132, in1); + let t137 = circuit_sub(t136, t133); + let t138 = circuit_sub(t135, t136); + let t139 = circuit_sub(t138, t133); + let t140 = circuit_add(t137, t104); // Fp2 add coeff 0/1 + let t141 = circuit_add(t139, t107); // Fp2 add coeff 1/1 + let t142 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t143 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t144 = circuit_add(t18, t20); // Fp2 add coeff 0/1 + let t145 = circuit_add(t19, t21); // Fp2 add coeff 1/1 + let t146 = circuit_mul(t142, t144); // Fp2 mul start + let t147 = circuit_mul(t143, t145); + let t148 = circuit_sub(t146, t147); // Fp2 mul real part end + let t149 = circuit_mul(t142, t145); + let t150 = circuit_mul(t143, t144); + let t151 = circuit_add(t149, t150); // Fp2 mul imag part end + let t152 = circuit_sub(t148, t104); // Fp2 sub coeff 0/1 + let t153 = circuit_sub(t151, t107); // Fp2 sub coeff 1/1 + let t154 = circuit_sub(t152, t110); // Fp2 sub coeff 0/1 + let t155 = circuit_sub(t153, t113); // Fp2 sub coeff 1/1 + let t156 = circuit_add(t116, t119); + let t157 = circuit_mul(t156, in0); + let t158 = circuit_mul(t116, in1); + let t159 = circuit_sub(t158, t119); + let t160 = circuit_sub(t157, t158); + let t161 = circuit_sub(t160, t119); + let t162 = circuit_add(t154, t159); // Fp2 add coeff 0/1 + let t163 = circuit_add(t155, t161); // Fp2 add coeff 1/1 + let t164 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t165 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t166 = circuit_add(t18, t22); // Fp2 add coeff 0/1 + let t167 = circuit_add(t19, t23); // Fp2 add coeff 1/1 + let t168 = circuit_mul(t166, t164); // Fp2 mul start + let t169 = circuit_mul(t167, t165); + let t170 = circuit_sub(t168, t169); // Fp2 mul real part end + let t171 = circuit_mul(t166, t165); + let t172 = circuit_mul(t167, t164); + let t173 = circuit_add(t171, t172); // Fp2 mul imag part end + let t174 = circuit_sub(t170, t104); // Fp2 sub coeff 0/1 + let t175 = circuit_sub(t173, t107); // Fp2 sub coeff 1/1 + let t176 = circuit_sub(t174, t116); // Fp2 sub coeff 0/1 + let t177 = circuit_sub(t175, t119); // Fp2 sub coeff 1/1 + let t178 = circuit_add(t176, t110); // Fp2 add coeff 0/1 + let t179 = circuit_add(t177, t113); // Fp2 add coeff 1/1 + let t180 = circuit_add(t140, t62); // Fp6 add coeff 0/5 + let t181 = circuit_add(t141, t63); // Fp6 add coeff 1/5 + let t182 = circuit_add(t162, t84); // Fp6 add coeff 2/5 + let t183 = circuit_add(t163, t85); // Fp6 add coeff 3/5 + let t184 = circuit_add(t178, t100); // Fp6 add coeff 4/5 + let t185 = circuit_add(t179, t101); // Fp6 add coeff 5/5 + let t186 = circuit_add(t62, t62); // Fp6 add coeff 0/5 + let t187 = circuit_add(t63, t63); // Fp6 add coeff 1/5 + let t188 = circuit_add(t84, t84); // Fp6 add coeff 2/5 + let t189 = circuit_add(t85, t85); // Fp6 add coeff 3/5 + let t190 = circuit_add(t100, t100); // Fp6 add coeff 4/5 + let t191 = circuit_add(t101, t101); // Fp6 add coeff 5/5 + let t192 = circuit_add(t100, t101); + let t193 = circuit_mul(t192, in0); + let t194 = circuit_mul(t100, in1); + let t195 = circuit_sub(t194, t101); + let t196 = circuit_sub(t193, t194); + let t197 = circuit_sub(t196, t101); + let t198 = circuit_add(t180, t195); // Fp6 add coeff 0/5 + let t199 = circuit_add(t181, t197); // Fp6 add coeff 1/5 + let t200 = circuit_add(t182, t62); // Fp6 add coeff 2/5 + let t201 = circuit_add(t183, t63); // Fp6 add coeff 3/5 + let t202 = circuit_add(t184, t84); // Fp6 add coeff 4/5 + let t203 = circuit_add(t185, t85); // Fp6 add coeff 5/5 + let t204 = circuit_add(in8, in9); // Doubling slope numerator start + let t205 = circuit_sub(in8, in9); + let t206 = circuit_mul(t204, t205); + let t207 = circuit_mul(in8, in9); + let t208 = circuit_mul(t206, in3); + let t209 = circuit_mul(t207, in4); // Doubling slope numerator end + let t210 = circuit_add(in10, in10); // Fp2 add coeff 0/1 + let t211 = circuit_add(in11, in11); // Fp2 add coeff 1/1 + let t212 = circuit_mul(t210, t210); // Fp2 Inv start + let t213 = circuit_mul(t211, t211); + let t214 = circuit_add(t212, t213); + let t215 = circuit_inverse(t214); + let t216 = circuit_mul(t210, t215); // Fp2 Inv real part end + let t217 = circuit_mul(t211, t215); + let t218 = circuit_sub(in2, t217); // Fp2 Inv imag part end + let t219 = circuit_mul(t208, t216); // Fp2 mul start + let t220 = circuit_mul(t209, t218); + let t221 = circuit_sub(t219, t220); // Fp2 mul real part end + let t222 = circuit_mul(t208, t218); + let t223 = circuit_mul(t209, t216); + let t224 = circuit_add(t222, t223); // Fp2 mul imag part end + let t225 = circuit_add(t221, t224); + let t226 = circuit_sub(t221, t224); + let t227 = circuit_mul(t225, t226); + let t228 = circuit_mul(t221, t224); + let t229 = circuit_add(t228, t228); + let t230 = circuit_add(in8, in8); // Fp2 add coeff 0/1 + let t231 = circuit_add(in9, in9); // Fp2 add coeff 1/1 + let t232 = circuit_sub(t227, t230); // Fp2 sub coeff 0/1 + let t233 = circuit_sub(t229, t231); // Fp2 sub coeff 1/1 + let t234 = circuit_sub(in8, t232); // Fp2 sub coeff 0/1 + let t235 = circuit_sub(in9, t233); // Fp2 sub coeff 1/1 + let t236 = circuit_mul(t221, t234); // Fp2 mul start + let t237 = circuit_mul(t224, t235); + let t238 = circuit_sub(t236, t237); // Fp2 mul real part end + let t239 = circuit_mul(t221, t235); + let t240 = circuit_mul(t224, t234); + let t241 = circuit_add(t239, t240); // Fp2 mul imag part end + let t242 = circuit_sub(t238, in10); // Fp2 sub coeff 0/1 + let t243 = circuit_sub(t241, in11); // Fp2 sub coeff 1/1 + let t244 = circuit_mul(t221, in8); // Fp2 mul start + let t245 = circuit_mul(t224, in9); + let t246 = circuit_sub(t244, t245); // Fp2 mul real part end + let t247 = circuit_mul(t221, in9); + let t248 = circuit_mul(t224, in8); + let t249 = circuit_add(t247, t248); // Fp2 mul imag part end + let t250 = circuit_sub(t246, in10); // Fp2 sub coeff 0/1 + let t251 = circuit_sub(t249, in11); // Fp2 sub coeff 1/1 + let t252 = circuit_mul(t221, in7); + let t253 = circuit_mul(t224, in7); + let t254 = circuit_mul(t250, in6); + let t255 = circuit_mul(t251, in6); + let t256 = circuit_mul(t186, t252); // Fp2 mul start + let t257 = circuit_mul(t187, t253); + let t258 = circuit_sub(t256, t257); // Fp2 mul real part end + let t259 = circuit_mul(t186, t253); + let t260 = circuit_mul(t187, t252); + let t261 = circuit_add(t259, t260); // Fp2 mul imag part end + let t262 = circuit_mul(t188, t254); // Fp2 mul start + let t263 = circuit_mul(t189, t255); + let t264 = circuit_sub(t262, t263); // Fp2 mul real part end + let t265 = circuit_mul(t188, t255); + let t266 = circuit_mul(t189, t254); + let t267 = circuit_add(t265, t266); // Fp2 mul imag part end + let t268 = circuit_add(t188, t190); // Fp2 add coeff 0/1 + let t269 = circuit_add(t189, t191); // Fp2 add coeff 1/1 + let t270 = circuit_mul(t254, t268); // Fp2 mul start + let t271 = circuit_mul(t255, t269); + let t272 = circuit_sub(t270, t271); // Fp2 mul real part end + let t273 = circuit_mul(t254, t269); + let t274 = circuit_mul(t255, t268); + let t275 = circuit_add(t273, t274); // Fp2 mul imag part end + let t276 = circuit_sub(t272, t264); // Fp2 sub coeff 0/1 + let t277 = circuit_sub(t275, t267); // Fp2 sub coeff 1/1 + let t278 = circuit_add(t276, t277); + let t279 = circuit_mul(t278, in0); + let t280 = circuit_mul(t276, in1); + let t281 = circuit_sub(t280, t277); + let t282 = circuit_sub(t279, t280); + let t283 = circuit_sub(t282, t277); + let t284 = circuit_add(t281, t258); // Fp2 add coeff 0/1 + let t285 = circuit_add(t283, t261); // Fp2 add coeff 1/1 + let t286 = circuit_add(t186, t190); // Fp2 add coeff 0/1 + let t287 = circuit_add(t187, t191); // Fp2 add coeff 1/1 + let t288 = circuit_mul(t252, t286); // Fp2 mul start + let t289 = circuit_mul(t253, t287); + let t290 = circuit_sub(t288, t289); // Fp2 mul real part end + let t291 = circuit_mul(t252, t287); + let t292 = circuit_mul(t253, t286); + let t293 = circuit_add(t291, t292); // Fp2 mul imag part end + let t294 = circuit_sub(t290, t258); // Fp2 sub coeff 0/1 + let t295 = circuit_sub(t293, t261); // Fp2 sub coeff 1/1 + let t296 = circuit_add(t294, t264); // Fp2 add coeff 0/1 + let t297 = circuit_add(t295, t267); // Fp2 add coeff 1/1 + let t298 = circuit_add(t252, t254); // Fp2 add coeff 0/1 + let t299 = circuit_add(t253, t255); // Fp2 add coeff 1/1 + let t300 = circuit_add(t186, t188); // Fp2 add coeff 0/1 + let t301 = circuit_add(t187, t189); // Fp2 add coeff 1/1 + let t302 = circuit_mul(t298, t300); // Fp2 mul start + let t303 = circuit_mul(t299, t301); + let t304 = circuit_sub(t302, t303); // Fp2 mul real part end + let t305 = circuit_mul(t298, t301); + let t306 = circuit_mul(t299, t300); + let t307 = circuit_add(t305, t306); // Fp2 mul imag part end + let t308 = circuit_sub(t304, t258); // Fp2 sub coeff 0/1 + let t309 = circuit_sub(t307, t261); // Fp2 sub coeff 1/1 + let t310 = circuit_sub(t308, t264); // Fp2 sub coeff 0/1 + let t311 = circuit_sub(t309, t267); // Fp2 sub coeff 1/1 + let t312 = circuit_add(in5, t252); // Fp2 add coeff 0/1 + let t313 = circuit_add(in2, t253); // Fp2 add coeff 1/1 + let t314 = circuit_add(t198, t186); // Fp6 add coeff 0/5 + let t315 = circuit_add(t199, t187); // Fp6 add coeff 1/5 + let t316 = circuit_add(t200, t188); // Fp6 add coeff 2/5 + let t317 = circuit_add(t201, t189); // Fp6 add coeff 3/5 + let t318 = circuit_add(t202, t190); // Fp6 add coeff 4/5 + let t319 = circuit_add(t203, t191); // Fp6 add coeff 5/5 + let t320 = circuit_mul(t314, t312); // Fp2 mul start + let t321 = circuit_mul(t315, t313); + let t322 = circuit_sub(t320, t321); // Fp2 mul real part end + let t323 = circuit_mul(t314, t313); + let t324 = circuit_mul(t315, t312); + let t325 = circuit_add(t323, t324); // Fp2 mul imag part end + let t326 = circuit_mul(t316, t254); // Fp2 mul start + let t327 = circuit_mul(t317, t255); + let t328 = circuit_sub(t326, t327); // Fp2 mul real part end + let t329 = circuit_mul(t316, t255); + let t330 = circuit_mul(t317, t254); + let t331 = circuit_add(t329, t330); // Fp2 mul imag part end + let t332 = circuit_add(t316, t318); // Fp2 add coeff 0/1 + let t333 = circuit_add(t317, t319); // Fp2 add coeff 1/1 + let t334 = circuit_mul(t254, t332); // Fp2 mul start + let t335 = circuit_mul(t255, t333); + let t336 = circuit_sub(t334, t335); // Fp2 mul real part end + let t337 = circuit_mul(t254, t333); + let t338 = circuit_mul(t255, t332); + let t339 = circuit_add(t337, t338); // Fp2 mul imag part end + let t340 = circuit_sub(t336, t328); // Fp2 sub coeff 0/1 + let t341 = circuit_sub(t339, t331); // Fp2 sub coeff 1/1 + let t342 = circuit_add(t340, t341); + let t343 = circuit_mul(t342, in0); + let t344 = circuit_mul(t340, in1); + let t345 = circuit_sub(t344, t341); + let t346 = circuit_sub(t343, t344); + let t347 = circuit_sub(t346, t341); + let t348 = circuit_add(t345, t322); // Fp2 add coeff 0/1 + let t349 = circuit_add(t347, t325); // Fp2 add coeff 1/1 + let t350 = circuit_add(t314, t318); // Fp2 add coeff 0/1 + let t351 = circuit_add(t315, t319); // Fp2 add coeff 1/1 + let t352 = circuit_mul(t312, t350); // Fp2 mul start + let t353 = circuit_mul(t313, t351); + let t354 = circuit_sub(t352, t353); // Fp2 mul real part end + let t355 = circuit_mul(t312, t351); + let t356 = circuit_mul(t313, t350); + let t357 = circuit_add(t355, t356); // Fp2 mul imag part end + let t358 = circuit_sub(t354, t322); // Fp2 sub coeff 0/1 + let t359 = circuit_sub(t357, t325); // Fp2 sub coeff 1/1 + let t360 = circuit_add(t358, t328); // Fp2 add coeff 0/1 + let t361 = circuit_add(t359, t331); // Fp2 add coeff 1/1 + let t362 = circuit_add(t312, t254); // Fp2 add coeff 0/1 + let t363 = circuit_add(t313, t255); // Fp2 add coeff 1/1 + let t364 = circuit_add(t314, t316); // Fp2 add coeff 0/1 + let t365 = circuit_add(t315, t317); // Fp2 add coeff 1/1 + let t366 = circuit_mul(t362, t364); // Fp2 mul start + let t367 = circuit_mul(t363, t365); + let t368 = circuit_sub(t366, t367); // Fp2 mul real part end + let t369 = circuit_mul(t362, t365); + let t370 = circuit_mul(t363, t364); + let t371 = circuit_add(t369, t370); // Fp2 mul imag part end + let t372 = circuit_sub(t368, t322); // Fp2 sub coeff 0/1 + let t373 = circuit_sub(t371, t325); // Fp2 sub coeff 1/1 + let t374 = circuit_sub(t372, t328); // Fp2 sub coeff 0/1 + let t375 = circuit_sub(t373, t331); // Fp2 sub coeff 1/1 + let t376 = circuit_add(t198, t284); // Fp6 add coeff 0/5 + let t377 = circuit_add(t199, t285); // Fp6 add coeff 1/5 + let t378 = circuit_add(t200, t310); // Fp6 add coeff 2/5 + let t379 = circuit_add(t201, t311); // Fp6 add coeff 3/5 + let t380 = circuit_add(t202, t296); // Fp6 add coeff 4/5 + let t381 = circuit_add(t203, t297); // Fp6 add coeff 5/5 + let t382 = circuit_sub(in2, t376); // Fp6 neg coeff 0/5 + let t383 = circuit_sub(in2, t377); // Fp6 neg coeff 1/5 + let t384 = circuit_sub(in2, t378); // Fp6 neg coeff 2/5 + let t385 = circuit_sub(in2, t379); // Fp6 neg coeff 3/5 + let t386 = circuit_sub(in2, t380); // Fp6 neg coeff 4/5 + let t387 = circuit_sub(in2, t381); // Fp6 neg coeff 5/5 + let t388 = circuit_add(t382, t348); // Fp6 add coeff 0/5 + let t389 = circuit_add(t383, t349); // Fp6 add coeff 1/5 + let t390 = circuit_add(t384, t374); // Fp6 add coeff 2/5 + let t391 = circuit_add(t385, t375); // Fp6 add coeff 3/5 + let t392 = circuit_add(t386, t360); // Fp6 add coeff 4/5 + let t393 = circuit_add(t387, t361); // Fp6 add coeff 5/5 + let t394 = circuit_add(t296, t297); + let t395 = circuit_mul(t394, in0); + let t396 = circuit_mul(t296, in1); + let t397 = circuit_sub(t396, t297); + let t398 = circuit_sub(t395, t396); + let t399 = circuit_sub(t398, t297); + let t400 = circuit_add(t397, t198); // Fp6 add coeff 0/5 + let t401 = circuit_add(t399, t199); // Fp6 add coeff 1/5 + let t402 = circuit_add(t284, t200); // Fp6 add coeff 2/5 + let t403 = circuit_add(t285, t201); // Fp6 add coeff 3/5 + let t404 = circuit_add(t310, t202); // Fp6 add coeff 4/5 + let t405 = circuit_add(t311, t203); // Fp6 add coeff 5/5 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = ( + t232, + t233, + t242, + t243, + t400, + t401, + t402, + t403, + t404, + t405, + t388, + t389, + t390, + t391, + t392, + t393, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0xa, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x9, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in2 + circuit_inputs = circuit_inputs.next_2([0x3, 0x0, 0x0, 0x0]); // in3 + circuit_inputs = circuit_inputs.next_2([0x6, 0x0, 0x0, 0x0]); // in4 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in5 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(yInv_0); // in6 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in7 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in8 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in9 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in10 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in11 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a0); // in12 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a1); // in13 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a0); // in14 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a1); // in15 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a0); // in16 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a1); // in17 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a0); // in18 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a1); // in19 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a0); // in20 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a1); // in21 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a0); // in22 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a1); // in23 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Q0: G2Point = G2Point { + x0: outputs.get_output(t232), + x1: outputs.get_output(t233), + y0: outputs.get_output(t242), + y1: outputs.get_output(t243) + }; + let Mi_plus_one: E12T = E12T { + c0b0a0: outputs.get_output(t400), + c0b0a1: outputs.get_output(t401), + c0b1a0: outputs.get_output(t402), + c0b1a1: outputs.get_output(t403), + c0b2a0: outputs.get_output(t404), + c0b2a1: outputs.get_output(t405), + c1b0a0: outputs.get_output(t388), + c1b0a1: outputs.get_output(t389), + c1b1a0: outputs.get_output(t390), + c1b1a1: outputs.get_output(t391), + c1b2a0: outputs.get_output(t392), + c1b2a1: outputs.get_output(t393), + }; + return (Q0, Mi_plus_one); +} +#[inline(always)] +fn run_BN254_TOWER_MILLER_BIT1_1P_circuit( + yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point, Q_or_Q_neg_0: G2Point, M_i: E12T +) -> (G2Point, E12T) { + // CONSTANT stack + let in0 = CE::> {}; // 0xa + let in1 = CE::> {}; // 0x9 + let in2 = CE::> {}; // 0x0 + let in3 = CE::> {}; // 0x1 + + // INPUT stack + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let (in7, in8, in9) = (CE::> {}, CE::> {}, CE::> {}); + let (in10, in11, in12) = (CE::> {}, CE::> {}, CE::> {}); + let (in13, in14, in15) = (CE::> {}, CE::> {}, CE::> {}); + let (in16, in17, in18) = (CE::> {}, CE::> {}, CE::> {}); + let (in19, in20, in21) = (CE::> {}, CE::> {}, CE::> {}); + let (in22, in23, in24) = (CE::> {}, CE::> {}, CE::> {}); + let in25 = CE::> {}; + let t0 = circuit_sub(in14, in20); // Fp6 sub coeff 0/5 + let t1 = circuit_sub(in15, in21); // Fp6 sub coeff 1/5 + let t2 = circuit_sub(in16, in22); // Fp6 sub coeff 2/5 + let t3 = circuit_sub(in17, in23); // Fp6 sub coeff 3/5 + let t4 = circuit_sub(in18, in24); // Fp6 sub coeff 4/5 + let t5 = circuit_sub(in19, in25); // Fp6 sub coeff 5/5 + let t6 = circuit_add(in24, in25); + let t7 = circuit_mul(t6, in0); + let t8 = circuit_mul(in24, in1); + let t9 = circuit_sub(t8, in25); + let t10 = circuit_sub(t7, t8); + let t11 = circuit_sub(t10, in25); + let t12 = circuit_sub(in2, t9); // Fp6 neg coeff 0/5 + let t13 = circuit_sub(in2, t11); // Fp6 neg coeff 1/5 + let t14 = circuit_sub(in2, in20); // Fp6 neg coeff 2/5 + let t15 = circuit_sub(in2, in21); // Fp6 neg coeff 3/5 + let t16 = circuit_sub(in2, in22); // Fp6 neg coeff 4/5 + let t17 = circuit_sub(in2, in23); // Fp6 neg coeff 5/5 + let t18 = circuit_add(in14, t12); // Fp6 add coeff 0/5 + let t19 = circuit_add(in15, t13); // Fp6 add coeff 1/5 + let t20 = circuit_add(in16, t14); // Fp6 add coeff 2/5 + let t21 = circuit_add(in17, t15); // Fp6 add coeff 3/5 + let t22 = circuit_add(in18, t16); // Fp6 add coeff 4/5 + let t23 = circuit_add(in19, t17); // Fp6 add coeff 5/5 + let t24 = circuit_mul(in14, in20); // Fp2 mul start + let t25 = circuit_mul(in15, in21); + let t26 = circuit_sub(t24, t25); // Fp2 mul real part end + let t27 = circuit_mul(in14, in21); + let t28 = circuit_mul(in15, in20); + let t29 = circuit_add(t27, t28); // Fp2 mul imag part end + let t30 = circuit_mul(in16, in22); // Fp2 mul start + let t31 = circuit_mul(in17, in23); + let t32 = circuit_sub(t30, t31); // Fp2 mul real part end + let t33 = circuit_mul(in16, in23); + let t34 = circuit_mul(in17, in22); + let t35 = circuit_add(t33, t34); // Fp2 mul imag part end + let t36 = circuit_mul(in18, in24); // Fp2 mul start + let t37 = circuit_mul(in19, in25); + let t38 = circuit_sub(t36, t37); // Fp2 mul real part end + let t39 = circuit_mul(in18, in25); + let t40 = circuit_mul(in19, in24); + let t41 = circuit_add(t39, t40); // Fp2 mul imag part end + let t42 = circuit_add(in16, in18); // Fp2 add coeff 0/1 + let t43 = circuit_add(in17, in19); // Fp2 add coeff 1/1 + let t44 = circuit_add(in22, in24); // Fp2 add coeff 0/1 + let t45 = circuit_add(in23, in25); // Fp2 add coeff 1/1 + let t46 = circuit_mul(t42, t44); // Fp2 mul start + let t47 = circuit_mul(t43, t45); + let t48 = circuit_sub(t46, t47); // Fp2 mul real part end + let t49 = circuit_mul(t42, t45); + let t50 = circuit_mul(t43, t44); + let t51 = circuit_add(t49, t50); // Fp2 mul imag part end + let t52 = circuit_sub(t48, t32); // Fp2 sub coeff 0/1 + let t53 = circuit_sub(t51, t35); // Fp2 sub coeff 1/1 + let t54 = circuit_sub(t52, t38); // Fp2 sub coeff 0/1 + let t55 = circuit_sub(t53, t41); // Fp2 sub coeff 1/1 + let t56 = circuit_add(t54, t55); + let t57 = circuit_mul(t56, in0); + let t58 = circuit_mul(t54, in1); + let t59 = circuit_sub(t58, t55); + let t60 = circuit_sub(t57, t58); + let t61 = circuit_sub(t60, t55); + let t62 = circuit_add(t59, t26); // Fp2 add coeff 0/1 + let t63 = circuit_add(t61, t29); // Fp2 add coeff 1/1 + let t64 = circuit_add(in14, in16); // Fp2 add coeff 0/1 + let t65 = circuit_add(in15, in17); // Fp2 add coeff 1/1 + let t66 = circuit_add(in20, in22); // Fp2 add coeff 0/1 + let t67 = circuit_add(in21, in23); // Fp2 add coeff 1/1 + let t68 = circuit_mul(t64, t66); // Fp2 mul start + let t69 = circuit_mul(t65, t67); + let t70 = circuit_sub(t68, t69); // Fp2 mul real part end + let t71 = circuit_mul(t64, t67); + let t72 = circuit_mul(t65, t66); + let t73 = circuit_add(t71, t72); // Fp2 mul imag part end + let t74 = circuit_sub(t70, t26); // Fp2 sub coeff 0/1 + let t75 = circuit_sub(t73, t29); // Fp2 sub coeff 1/1 + let t76 = circuit_sub(t74, t32); // Fp2 sub coeff 0/1 + let t77 = circuit_sub(t75, t35); // Fp2 sub coeff 1/1 + let t78 = circuit_add(t38, t41); + let t79 = circuit_mul(t78, in0); + let t80 = circuit_mul(t38, in1); + let t81 = circuit_sub(t80, t41); + let t82 = circuit_sub(t79, t80); + let t83 = circuit_sub(t82, t41); + let t84 = circuit_add(t76, t81); // Fp2 add coeff 0/1 + let t85 = circuit_add(t77, t83); // Fp2 add coeff 1/1 + let t86 = circuit_add(in14, in18); // Fp2 add coeff 0/1 + let t87 = circuit_add(in15, in19); // Fp2 add coeff 1/1 + let t88 = circuit_add(in20, in24); // Fp2 add coeff 0/1 + let t89 = circuit_add(in21, in25); // Fp2 add coeff 1/1 + let t90 = circuit_mul(t88, t86); // Fp2 mul start + let t91 = circuit_mul(t89, t87); + let t92 = circuit_sub(t90, t91); // Fp2 mul real part end + let t93 = circuit_mul(t88, t87); + let t94 = circuit_mul(t89, t86); + let t95 = circuit_add(t93, t94); // Fp2 mul imag part end + let t96 = circuit_sub(t92, t26); // Fp2 sub coeff 0/1 + let t97 = circuit_sub(t95, t29); // Fp2 sub coeff 1/1 + let t98 = circuit_sub(t96, t38); // Fp2 sub coeff 0/1 + let t99 = circuit_sub(t97, t41); // Fp2 sub coeff 1/1 + let t100 = circuit_add(t98, t32); // Fp2 add coeff 0/1 + let t101 = circuit_add(t99, t35); // Fp2 add coeff 1/1 + let t102 = circuit_mul(t0, t18); // Fp2 mul start + let t103 = circuit_mul(t1, t19); + let t104 = circuit_sub(t102, t103); // Fp2 mul real part end + let t105 = circuit_mul(t0, t19); + let t106 = circuit_mul(t1, t18); + let t107 = circuit_add(t105, t106); // Fp2 mul imag part end + let t108 = circuit_mul(t2, t20); // Fp2 mul start + let t109 = circuit_mul(t3, t21); + let t110 = circuit_sub(t108, t109); // Fp2 mul real part end + let t111 = circuit_mul(t2, t21); + let t112 = circuit_mul(t3, t20); + let t113 = circuit_add(t111, t112); // Fp2 mul imag part end + let t114 = circuit_mul(t4, t22); // Fp2 mul start + let t115 = circuit_mul(t5, t23); + let t116 = circuit_sub(t114, t115); // Fp2 mul real part end + let t117 = circuit_mul(t4, t23); + let t118 = circuit_mul(t5, t22); + let t119 = circuit_add(t117, t118); // Fp2 mul imag part end + let t120 = circuit_add(t2, t4); // Fp2 add coeff 0/1 + let t121 = circuit_add(t3, t5); // Fp2 add coeff 1/1 + let t122 = circuit_add(t20, t22); // Fp2 add coeff 0/1 + let t123 = circuit_add(t21, t23); // Fp2 add coeff 1/1 + let t124 = circuit_mul(t120, t122); // Fp2 mul start + let t125 = circuit_mul(t121, t123); + let t126 = circuit_sub(t124, t125); // Fp2 mul real part end + let t127 = circuit_mul(t120, t123); + let t128 = circuit_mul(t121, t122); + let t129 = circuit_add(t127, t128); // Fp2 mul imag part end + let t130 = circuit_sub(t126, t110); // Fp2 sub coeff 0/1 + let t131 = circuit_sub(t129, t113); // Fp2 sub coeff 1/1 + let t132 = circuit_sub(t130, t116); // Fp2 sub coeff 0/1 + let t133 = circuit_sub(t131, t119); // Fp2 sub coeff 1/1 + let t134 = circuit_add(t132, t133); + let t135 = circuit_mul(t134, in0); + let t136 = circuit_mul(t132, in1); + let t137 = circuit_sub(t136, t133); + let t138 = circuit_sub(t135, t136); + let t139 = circuit_sub(t138, t133); + let t140 = circuit_add(t137, t104); // Fp2 add coeff 0/1 + let t141 = circuit_add(t139, t107); // Fp2 add coeff 1/1 + let t142 = circuit_add(t0, t2); // Fp2 add coeff 0/1 + let t143 = circuit_add(t1, t3); // Fp2 add coeff 1/1 + let t144 = circuit_add(t18, t20); // Fp2 add coeff 0/1 + let t145 = circuit_add(t19, t21); // Fp2 add coeff 1/1 + let t146 = circuit_mul(t142, t144); // Fp2 mul start + let t147 = circuit_mul(t143, t145); + let t148 = circuit_sub(t146, t147); // Fp2 mul real part end + let t149 = circuit_mul(t142, t145); + let t150 = circuit_mul(t143, t144); + let t151 = circuit_add(t149, t150); // Fp2 mul imag part end + let t152 = circuit_sub(t148, t104); // Fp2 sub coeff 0/1 + let t153 = circuit_sub(t151, t107); // Fp2 sub coeff 1/1 + let t154 = circuit_sub(t152, t110); // Fp2 sub coeff 0/1 + let t155 = circuit_sub(t153, t113); // Fp2 sub coeff 1/1 + let t156 = circuit_add(t116, t119); + let t157 = circuit_mul(t156, in0); + let t158 = circuit_mul(t116, in1); + let t159 = circuit_sub(t158, t119); + let t160 = circuit_sub(t157, t158); + let t161 = circuit_sub(t160, t119); + let t162 = circuit_add(t154, t159); // Fp2 add coeff 0/1 + let t163 = circuit_add(t155, t161); // Fp2 add coeff 1/1 + let t164 = circuit_add(t0, t4); // Fp2 add coeff 0/1 + let t165 = circuit_add(t1, t5); // Fp2 add coeff 1/1 + let t166 = circuit_add(t18, t22); // Fp2 add coeff 0/1 + let t167 = circuit_add(t19, t23); // Fp2 add coeff 1/1 + let t168 = circuit_mul(t166, t164); // Fp2 mul start + let t169 = circuit_mul(t167, t165); + let t170 = circuit_sub(t168, t169); // Fp2 mul real part end + let t171 = circuit_mul(t166, t165); + let t172 = circuit_mul(t167, t164); + let t173 = circuit_add(t171, t172); // Fp2 mul imag part end + let t174 = circuit_sub(t170, t104); // Fp2 sub coeff 0/1 + let t175 = circuit_sub(t173, t107); // Fp2 sub coeff 1/1 + let t176 = circuit_sub(t174, t116); // Fp2 sub coeff 0/1 + let t177 = circuit_sub(t175, t119); // Fp2 sub coeff 1/1 + let t178 = circuit_add(t176, t110); // Fp2 add coeff 0/1 + let t179 = circuit_add(t177, t113); // Fp2 add coeff 1/1 + let t180 = circuit_add(t140, t62); // Fp6 add coeff 0/5 + let t181 = circuit_add(t141, t63); // Fp6 add coeff 1/5 + let t182 = circuit_add(t162, t84); // Fp6 add coeff 2/5 + let t183 = circuit_add(t163, t85); // Fp6 add coeff 3/5 + let t184 = circuit_add(t178, t100); // Fp6 add coeff 4/5 + let t185 = circuit_add(t179, t101); // Fp6 add coeff 5/5 + let t186 = circuit_add(t62, t62); // Fp6 add coeff 0/5 + let t187 = circuit_add(t63, t63); // Fp6 add coeff 1/5 + let t188 = circuit_add(t84, t84); // Fp6 add coeff 2/5 + let t189 = circuit_add(t85, t85); // Fp6 add coeff 3/5 + let t190 = circuit_add(t100, t100); // Fp6 add coeff 4/5 + let t191 = circuit_add(t101, t101); // Fp6 add coeff 5/5 + let t192 = circuit_add(t100, t101); + let t193 = circuit_mul(t192, in0); + let t194 = circuit_mul(t100, in1); + let t195 = circuit_sub(t194, t101); + let t196 = circuit_sub(t193, t194); + let t197 = circuit_sub(t196, t101); + let t198 = circuit_add(t180, t195); // Fp6 add coeff 0/5 + let t199 = circuit_add(t181, t197); // Fp6 add coeff 1/5 + let t200 = circuit_add(t182, t62); // Fp6 add coeff 2/5 + let t201 = circuit_add(t183, t63); // Fp6 add coeff 3/5 + let t202 = circuit_add(t184, t84); // Fp6 add coeff 4/5 + let t203 = circuit_add(t185, t85); // Fp6 add coeff 5/5 + let t204 = circuit_sub(in8, in12); // Fp2 sub coeff 0/1 + let t205 = circuit_sub(in9, in13); // Fp2 sub coeff 1/1 + let t206 = circuit_sub(in6, in10); // Fp2 sub coeff 0/1 + let t207 = circuit_sub(in7, in11); // Fp2 sub coeff 1/1 + let t208 = circuit_mul(t206, t206); // Fp2 Inv start + let t209 = circuit_mul(t207, t207); + let t210 = circuit_add(t208, t209); + let t211 = circuit_inverse(t210); + let t212 = circuit_mul(t206, t211); // Fp2 Inv real part end + let t213 = circuit_mul(t207, t211); + let t214 = circuit_sub(in2, t213); // Fp2 Inv imag part end + let t215 = circuit_mul(t204, t212); // Fp2 mul start + let t216 = circuit_mul(t205, t214); + let t217 = circuit_sub(t215, t216); // Fp2 mul real part end + let t218 = circuit_mul(t204, t214); + let t219 = circuit_mul(t205, t212); + let t220 = circuit_add(t218, t219); // Fp2 mul imag part end + let t221 = circuit_add(t217, t220); + let t222 = circuit_sub(t217, t220); + let t223 = circuit_mul(t221, t222); + let t224 = circuit_mul(t217, t220); + let t225 = circuit_add(t224, t224); + let t226 = circuit_add(in6, in10); // Fp2 add coeff 0/1 + let t227 = circuit_add(in7, in11); // Fp2 add coeff 1/1 + let t228 = circuit_sub(t223, t226); // Fp2 sub coeff 0/1 + let t229 = circuit_sub(t225, t227); // Fp2 sub coeff 1/1 + let t230 = circuit_mul(t217, in6); // Fp2 mul start + let t231 = circuit_mul(t220, in7); + let t232 = circuit_sub(t230, t231); // Fp2 mul real part end + let t233 = circuit_mul(t217, in7); + let t234 = circuit_mul(t220, in6); + let t235 = circuit_add(t233, t234); // Fp2 mul imag part end + let t236 = circuit_sub(t232, in8); // Fp2 sub coeff 0/1 + let t237 = circuit_sub(t235, in9); // Fp2 sub coeff 1/1 + let t238 = circuit_add(in8, in8); // Fp2 add coeff 0/1 + let t239 = circuit_add(in9, in9); // Fp2 add coeff 1/1 + let t240 = circuit_sub(t228, in6); // Fp2 sub coeff 0/1 + let t241 = circuit_sub(t229, in7); // Fp2 sub coeff 1/1 + let t242 = circuit_mul(t240, t240); // Fp2 Inv start + let t243 = circuit_mul(t241, t241); + let t244 = circuit_add(t242, t243); + let t245 = circuit_inverse(t244); + let t246 = circuit_mul(t240, t245); // Fp2 Inv real part end + let t247 = circuit_mul(t241, t245); + let t248 = circuit_sub(in2, t247); // Fp2 Inv imag part end + let t249 = circuit_mul(t238, t246); // Fp2 mul start + let t250 = circuit_mul(t239, t248); + let t251 = circuit_sub(t249, t250); // Fp2 mul real part end + let t252 = circuit_mul(t238, t248); + let t253 = circuit_mul(t239, t246); + let t254 = circuit_add(t252, t253); // Fp2 mul imag part end + let t255 = circuit_add(t217, t251); // Fp2 add coeff 0/1 + let t256 = circuit_add(t220, t254); // Fp2 add coeff 1/1 + let t257 = circuit_sub(in2, t255); // Fp2 neg coeff 0/1 + let t258 = circuit_sub(in2, t256); // Fp2 neg coeff 1/1 + let t259 = circuit_add(t257, t258); + let t260 = circuit_sub(t257, t258); + let t261 = circuit_mul(t259, t260); + let t262 = circuit_mul(t257, t258); + let t263 = circuit_add(t262, t262); + let t264 = circuit_sub(t261, in6); // Fp2 sub coeff 0/1 + let t265 = circuit_sub(t263, in7); // Fp2 sub coeff 1/1 + let t266 = circuit_sub(t264, t228); // Fp2 sub coeff 0/1 + let t267 = circuit_sub(t265, t229); // Fp2 sub coeff 1/1 + let t268 = circuit_sub(in6, t266); // Fp2 sub coeff 0/1 + let t269 = circuit_sub(in7, t267); // Fp2 sub coeff 1/1 + let t270 = circuit_mul(t257, t268); // Fp2 mul start + let t271 = circuit_mul(t258, t269); + let t272 = circuit_sub(t270, t271); // Fp2 mul real part end + let t273 = circuit_mul(t257, t269); + let t274 = circuit_mul(t258, t268); + let t275 = circuit_add(t273, t274); // Fp2 mul imag part end + let t276 = circuit_sub(t272, in8); // Fp2 sub coeff 0/1 + let t277 = circuit_sub(t275, in9); // Fp2 sub coeff 1/1 + let t278 = circuit_mul(t257, in6); // Fp2 mul start + let t279 = circuit_mul(t258, in7); + let t280 = circuit_sub(t278, t279); // Fp2 mul real part end + let t281 = circuit_mul(t257, in7); + let t282 = circuit_mul(t258, in6); + let t283 = circuit_add(t281, t282); // Fp2 mul imag part end + let t284 = circuit_sub(t280, in8); // Fp2 sub coeff 0/1 + let t285 = circuit_sub(t283, in9); // Fp2 sub coeff 1/1 + let t286 = circuit_mul(t217, in5); + let t287 = circuit_mul(t220, in5); + let t288 = circuit_mul(t236, in4); + let t289 = circuit_mul(t237, in4); + let t290 = circuit_mul(t257, in5); + let t291 = circuit_mul(t258, in5); + let t292 = circuit_mul(t284, in4); + let t293 = circuit_mul(t285, in4); + let t294 = circuit_mul(t186, t286); // Fp2 mul start + let t295 = circuit_mul(t187, t287); + let t296 = circuit_sub(t294, t295); // Fp2 mul real part end + let t297 = circuit_mul(t186, t287); + let t298 = circuit_mul(t187, t286); + let t299 = circuit_add(t297, t298); // Fp2 mul imag part end + let t300 = circuit_mul(t188, t288); // Fp2 mul start + let t301 = circuit_mul(t189, t289); + let t302 = circuit_sub(t300, t301); // Fp2 mul real part end + let t303 = circuit_mul(t188, t289); + let t304 = circuit_mul(t189, t288); + let t305 = circuit_add(t303, t304); // Fp2 mul imag part end + let t306 = circuit_add(t188, t190); // Fp2 add coeff 0/1 + let t307 = circuit_add(t189, t191); // Fp2 add coeff 1/1 + let t308 = circuit_mul(t288, t306); // Fp2 mul start + let t309 = circuit_mul(t289, t307); + let t310 = circuit_sub(t308, t309); // Fp2 mul real part end + let t311 = circuit_mul(t288, t307); + let t312 = circuit_mul(t289, t306); + let t313 = circuit_add(t311, t312); // Fp2 mul imag part end + let t314 = circuit_sub(t310, t302); // Fp2 sub coeff 0/1 + let t315 = circuit_sub(t313, t305); // Fp2 sub coeff 1/1 + let t316 = circuit_add(t314, t315); + let t317 = circuit_mul(t316, in0); + let t318 = circuit_mul(t314, in1); + let t319 = circuit_sub(t318, t315); + let t320 = circuit_sub(t317, t318); + let t321 = circuit_sub(t320, t315); + let t322 = circuit_add(t319, t296); // Fp2 add coeff 0/1 + let t323 = circuit_add(t321, t299); // Fp2 add coeff 1/1 + let t324 = circuit_add(t186, t190); // Fp2 add coeff 0/1 + let t325 = circuit_add(t187, t191); // Fp2 add coeff 1/1 + let t326 = circuit_mul(t286, t324); // Fp2 mul start + let t327 = circuit_mul(t287, t325); + let t328 = circuit_sub(t326, t327); // Fp2 mul real part end + let t329 = circuit_mul(t286, t325); + let t330 = circuit_mul(t287, t324); + let t331 = circuit_add(t329, t330); // Fp2 mul imag part end + let t332 = circuit_sub(t328, t296); // Fp2 sub coeff 0/1 + let t333 = circuit_sub(t331, t299); // Fp2 sub coeff 1/1 + let t334 = circuit_add(t332, t302); // Fp2 add coeff 0/1 + let t335 = circuit_add(t333, t305); // Fp2 add coeff 1/1 + let t336 = circuit_add(t286, t288); // Fp2 add coeff 0/1 + let t337 = circuit_add(t287, t289); // Fp2 add coeff 1/1 + let t338 = circuit_add(t186, t188); // Fp2 add coeff 0/1 + let t339 = circuit_add(t187, t189); // Fp2 add coeff 1/1 + let t340 = circuit_mul(t336, t338); // Fp2 mul start + let t341 = circuit_mul(t337, t339); + let t342 = circuit_sub(t340, t341); // Fp2 mul real part end + let t343 = circuit_mul(t336, t339); + let t344 = circuit_mul(t337, t338); + let t345 = circuit_add(t343, t344); // Fp2 mul imag part end + let t346 = circuit_sub(t342, t296); // Fp2 sub coeff 0/1 + let t347 = circuit_sub(t345, t299); // Fp2 sub coeff 1/1 + let t348 = circuit_sub(t346, t302); // Fp2 sub coeff 0/1 + let t349 = circuit_sub(t347, t305); // Fp2 sub coeff 1/1 + let t350 = circuit_add(in3, t286); // Fp2 add coeff 0/1 + let t351 = circuit_add(in2, t287); // Fp2 add coeff 1/1 + let t352 = circuit_add(t198, t186); // Fp6 add coeff 0/5 + let t353 = circuit_add(t199, t187); // Fp6 add coeff 1/5 + let t354 = circuit_add(t200, t188); // Fp6 add coeff 2/5 + let t355 = circuit_add(t201, t189); // Fp6 add coeff 3/5 + let t356 = circuit_add(t202, t190); // Fp6 add coeff 4/5 + let t357 = circuit_add(t203, t191); // Fp6 add coeff 5/5 + let t358 = circuit_mul(t352, t350); // Fp2 mul start + let t359 = circuit_mul(t353, t351); + let t360 = circuit_sub(t358, t359); // Fp2 mul real part end + let t361 = circuit_mul(t352, t351); + let t362 = circuit_mul(t353, t350); + let t363 = circuit_add(t361, t362); // Fp2 mul imag part end + let t364 = circuit_mul(t354, t288); // Fp2 mul start + let t365 = circuit_mul(t355, t289); + let t366 = circuit_sub(t364, t365); // Fp2 mul real part end + let t367 = circuit_mul(t354, t289); + let t368 = circuit_mul(t355, t288); + let t369 = circuit_add(t367, t368); // Fp2 mul imag part end + let t370 = circuit_add(t354, t356); // Fp2 add coeff 0/1 + let t371 = circuit_add(t355, t357); // Fp2 add coeff 1/1 + let t372 = circuit_mul(t288, t370); // Fp2 mul start + let t373 = circuit_mul(t289, t371); + let t374 = circuit_sub(t372, t373); // Fp2 mul real part end + let t375 = circuit_mul(t288, t371); + let t376 = circuit_mul(t289, t370); + let t377 = circuit_add(t375, t376); // Fp2 mul imag part end + let t378 = circuit_sub(t374, t366); // Fp2 sub coeff 0/1 + let t379 = circuit_sub(t377, t369); // Fp2 sub coeff 1/1 + let t380 = circuit_add(t378, t379); + let t381 = circuit_mul(t380, in0); + let t382 = circuit_mul(t378, in1); + let t383 = circuit_sub(t382, t379); + let t384 = circuit_sub(t381, t382); + let t385 = circuit_sub(t384, t379); + let t386 = circuit_add(t383, t360); // Fp2 add coeff 0/1 + let t387 = circuit_add(t385, t363); // Fp2 add coeff 1/1 + let t388 = circuit_add(t352, t356); // Fp2 add coeff 0/1 + let t389 = circuit_add(t353, t357); // Fp2 add coeff 1/1 + let t390 = circuit_mul(t350, t388); // Fp2 mul start + let t391 = circuit_mul(t351, t389); + let t392 = circuit_sub(t390, t391); // Fp2 mul real part end + let t393 = circuit_mul(t350, t389); + let t394 = circuit_mul(t351, t388); + let t395 = circuit_add(t393, t394); // Fp2 mul imag part end + let t396 = circuit_sub(t392, t360); // Fp2 sub coeff 0/1 + let t397 = circuit_sub(t395, t363); // Fp2 sub coeff 1/1 + let t398 = circuit_add(t396, t366); // Fp2 add coeff 0/1 + let t399 = circuit_add(t397, t369); // Fp2 add coeff 1/1 + let t400 = circuit_add(t350, t288); // Fp2 add coeff 0/1 + let t401 = circuit_add(t351, t289); // Fp2 add coeff 1/1 + let t402 = circuit_add(t352, t354); // Fp2 add coeff 0/1 + let t403 = circuit_add(t353, t355); // Fp2 add coeff 1/1 + let t404 = circuit_mul(t400, t402); // Fp2 mul start + let t405 = circuit_mul(t401, t403); + let t406 = circuit_sub(t404, t405); // Fp2 mul real part end + let t407 = circuit_mul(t400, t403); + let t408 = circuit_mul(t401, t402); + let t409 = circuit_add(t407, t408); // Fp2 mul imag part end + let t410 = circuit_sub(t406, t360); // Fp2 sub coeff 0/1 + let t411 = circuit_sub(t409, t363); // Fp2 sub coeff 1/1 + let t412 = circuit_sub(t410, t366); // Fp2 sub coeff 0/1 + let t413 = circuit_sub(t411, t369); // Fp2 sub coeff 1/1 + let t414 = circuit_add(t198, t322); // Fp6 add coeff 0/5 + let t415 = circuit_add(t199, t323); // Fp6 add coeff 1/5 + let t416 = circuit_add(t200, t348); // Fp6 add coeff 2/5 + let t417 = circuit_add(t201, t349); // Fp6 add coeff 3/5 + let t418 = circuit_add(t202, t334); // Fp6 add coeff 4/5 + let t419 = circuit_add(t203, t335); // Fp6 add coeff 5/5 + let t420 = circuit_sub(in2, t414); // Fp6 neg coeff 0/5 + let t421 = circuit_sub(in2, t415); // Fp6 neg coeff 1/5 + let t422 = circuit_sub(in2, t416); // Fp6 neg coeff 2/5 + let t423 = circuit_sub(in2, t417); // Fp6 neg coeff 3/5 + let t424 = circuit_sub(in2, t418); // Fp6 neg coeff 4/5 + let t425 = circuit_sub(in2, t419); // Fp6 neg coeff 5/5 + let t426 = circuit_add(t420, t386); // Fp6 add coeff 0/5 + let t427 = circuit_add(t421, t387); // Fp6 add coeff 1/5 + let t428 = circuit_add(t422, t412); // Fp6 add coeff 2/5 + let t429 = circuit_add(t423, t413); // Fp6 add coeff 3/5 + let t430 = circuit_add(t424, t398); // Fp6 add coeff 4/5 + let t431 = circuit_add(t425, t399); // Fp6 add coeff 5/5 + let t432 = circuit_add(t334, t335); + let t433 = circuit_mul(t432, in0); + let t434 = circuit_mul(t334, in1); + let t435 = circuit_sub(t434, t335); + let t436 = circuit_sub(t433, t434); + let t437 = circuit_sub(t436, t335); + let t438 = circuit_add(t435, t198); // Fp6 add coeff 0/5 + let t439 = circuit_add(t437, t199); // Fp6 add coeff 1/5 + let t440 = circuit_add(t322, t200); // Fp6 add coeff 2/5 + let t441 = circuit_add(t323, t201); // Fp6 add coeff 3/5 + let t442 = circuit_add(t348, t202); // Fp6 add coeff 4/5 + let t443 = circuit_add(t349, t203); // Fp6 add coeff 5/5 + let t444 = circuit_mul(t426, t290); // Fp2 mul start + let t445 = circuit_mul(t427, t291); + let t446 = circuit_sub(t444, t445); // Fp2 mul real part end + let t447 = circuit_mul(t426, t291); + let t448 = circuit_mul(t427, t290); + let t449 = circuit_add(t447, t448); // Fp2 mul imag part end + let t450 = circuit_mul(t428, t292); // Fp2 mul start + let t451 = circuit_mul(t429, t293); + let t452 = circuit_sub(t450, t451); // Fp2 mul real part end + let t453 = circuit_mul(t428, t293); + let t454 = circuit_mul(t429, t292); + let t455 = circuit_add(t453, t454); // Fp2 mul imag part end + let t456 = circuit_add(t428, t430); // Fp2 add coeff 0/1 + let t457 = circuit_add(t429, t431); // Fp2 add coeff 1/1 + let t458 = circuit_mul(t292, t456); // Fp2 mul start + let t459 = circuit_mul(t293, t457); + let t460 = circuit_sub(t458, t459); // Fp2 mul real part end + let t461 = circuit_mul(t292, t457); + let t462 = circuit_mul(t293, t456); + let t463 = circuit_add(t461, t462); // Fp2 mul imag part end + let t464 = circuit_sub(t460, t452); // Fp2 sub coeff 0/1 + let t465 = circuit_sub(t463, t455); // Fp2 sub coeff 1/1 + let t466 = circuit_add(t464, t465); + let t467 = circuit_mul(t466, in0); + let t468 = circuit_mul(t464, in1); + let t469 = circuit_sub(t468, t465); + let t470 = circuit_sub(t467, t468); + let t471 = circuit_sub(t470, t465); + let t472 = circuit_add(t469, t446); // Fp2 add coeff 0/1 + let t473 = circuit_add(t471, t449); // Fp2 add coeff 1/1 + let t474 = circuit_add(t426, t430); // Fp2 add coeff 0/1 + let t475 = circuit_add(t427, t431); // Fp2 add coeff 1/1 + let t476 = circuit_mul(t290, t474); // Fp2 mul start + let t477 = circuit_mul(t291, t475); + let t478 = circuit_sub(t476, t477); // Fp2 mul real part end + let t479 = circuit_mul(t290, t475); + let t480 = circuit_mul(t291, t474); + let t481 = circuit_add(t479, t480); // Fp2 mul imag part end + let t482 = circuit_sub(t478, t446); // Fp2 sub coeff 0/1 + let t483 = circuit_sub(t481, t449); // Fp2 sub coeff 1/1 + let t484 = circuit_add(t482, t452); // Fp2 add coeff 0/1 + let t485 = circuit_add(t483, t455); // Fp2 add coeff 1/1 + let t486 = circuit_add(t290, t292); // Fp2 add coeff 0/1 + let t487 = circuit_add(t291, t293); // Fp2 add coeff 1/1 + let t488 = circuit_add(t426, t428); // Fp2 add coeff 0/1 + let t489 = circuit_add(t427, t429); // Fp2 add coeff 1/1 + let t490 = circuit_mul(t486, t488); // Fp2 mul start + let t491 = circuit_mul(t487, t489); + let t492 = circuit_sub(t490, t491); // Fp2 mul real part end + let t493 = circuit_mul(t486, t489); + let t494 = circuit_mul(t487, t488); + let t495 = circuit_add(t493, t494); // Fp2 mul imag part end + let t496 = circuit_sub(t492, t446); // Fp2 sub coeff 0/1 + let t497 = circuit_sub(t495, t449); // Fp2 sub coeff 1/1 + let t498 = circuit_sub(t496, t452); // Fp2 sub coeff 0/1 + let t499 = circuit_sub(t497, t455); // Fp2 sub coeff 1/1 + let t500 = circuit_add(in3, t290); // Fp2 add coeff 0/1 + let t501 = circuit_add(in2, t291); // Fp2 add coeff 1/1 + let t502 = circuit_add(t438, t426); // Fp6 add coeff 0/5 + let t503 = circuit_add(t439, t427); // Fp6 add coeff 1/5 + let t504 = circuit_add(t440, t428); // Fp6 add coeff 2/5 + let t505 = circuit_add(t441, t429); // Fp6 add coeff 3/5 + let t506 = circuit_add(t442, t430); // Fp6 add coeff 4/5 + let t507 = circuit_add(t443, t431); // Fp6 add coeff 5/5 + let t508 = circuit_mul(t502, t500); // Fp2 mul start + let t509 = circuit_mul(t503, t501); + let t510 = circuit_sub(t508, t509); // Fp2 mul real part end + let t511 = circuit_mul(t502, t501); + let t512 = circuit_mul(t503, t500); + let t513 = circuit_add(t511, t512); // Fp2 mul imag part end + let t514 = circuit_mul(t504, t292); // Fp2 mul start + let t515 = circuit_mul(t505, t293); + let t516 = circuit_sub(t514, t515); // Fp2 mul real part end + let t517 = circuit_mul(t504, t293); + let t518 = circuit_mul(t505, t292); + let t519 = circuit_add(t517, t518); // Fp2 mul imag part end + let t520 = circuit_add(t504, t506); // Fp2 add coeff 0/1 + let t521 = circuit_add(t505, t507); // Fp2 add coeff 1/1 + let t522 = circuit_mul(t292, t520); // Fp2 mul start + let t523 = circuit_mul(t293, t521); + let t524 = circuit_sub(t522, t523); // Fp2 mul real part end + let t525 = circuit_mul(t292, t521); + let t526 = circuit_mul(t293, t520); + let t527 = circuit_add(t525, t526); // Fp2 mul imag part end + let t528 = circuit_sub(t524, t516); // Fp2 sub coeff 0/1 + let t529 = circuit_sub(t527, t519); // Fp2 sub coeff 1/1 + let t530 = circuit_add(t528, t529); + let t531 = circuit_mul(t530, in0); + let t532 = circuit_mul(t528, in1); + let t533 = circuit_sub(t532, t529); + let t534 = circuit_sub(t531, t532); + let t535 = circuit_sub(t534, t529); + let t536 = circuit_add(t533, t510); // Fp2 add coeff 0/1 + let t537 = circuit_add(t535, t513); // Fp2 add coeff 1/1 + let t538 = circuit_add(t502, t506); // Fp2 add coeff 0/1 + let t539 = circuit_add(t503, t507); // Fp2 add coeff 1/1 + let t540 = circuit_mul(t500, t538); // Fp2 mul start + let t541 = circuit_mul(t501, t539); + let t542 = circuit_sub(t540, t541); // Fp2 mul real part end + let t543 = circuit_mul(t500, t539); + let t544 = circuit_mul(t501, t538); + let t545 = circuit_add(t543, t544); // Fp2 mul imag part end + let t546 = circuit_sub(t542, t510); // Fp2 sub coeff 0/1 + let t547 = circuit_sub(t545, t513); // Fp2 sub coeff 1/1 + let t548 = circuit_add(t546, t516); // Fp2 add coeff 0/1 + let t549 = circuit_add(t547, t519); // Fp2 add coeff 1/1 + let t550 = circuit_add(t500, t292); // Fp2 add coeff 0/1 + let t551 = circuit_add(t501, t293); // Fp2 add coeff 1/1 + let t552 = circuit_add(t502, t504); // Fp2 add coeff 0/1 + let t553 = circuit_add(t503, t505); // Fp2 add coeff 1/1 + let t554 = circuit_mul(t550, t552); // Fp2 mul start + let t555 = circuit_mul(t551, t553); + let t556 = circuit_sub(t554, t555); // Fp2 mul real part end + let t557 = circuit_mul(t550, t553); + let t558 = circuit_mul(t551, t552); + let t559 = circuit_add(t557, t558); // Fp2 mul imag part end + let t560 = circuit_sub(t556, t510); // Fp2 sub coeff 0/1 + let t561 = circuit_sub(t559, t513); // Fp2 sub coeff 1/1 + let t562 = circuit_sub(t560, t516); // Fp2 sub coeff 0/1 + let t563 = circuit_sub(t561, t519); // Fp2 sub coeff 1/1 + let t564 = circuit_add(t438, t472); // Fp6 add coeff 0/5 + let t565 = circuit_add(t439, t473); // Fp6 add coeff 1/5 + let t566 = circuit_add(t440, t498); // Fp6 add coeff 2/5 + let t567 = circuit_add(t441, t499); // Fp6 add coeff 3/5 + let t568 = circuit_add(t442, t484); // Fp6 add coeff 4/5 + let t569 = circuit_add(t443, t485); // Fp6 add coeff 5/5 + let t570 = circuit_sub(in2, t564); // Fp6 neg coeff 0/5 + let t571 = circuit_sub(in2, t565); // Fp6 neg coeff 1/5 + let t572 = circuit_sub(in2, t566); // Fp6 neg coeff 2/5 + let t573 = circuit_sub(in2, t567); // Fp6 neg coeff 3/5 + let t574 = circuit_sub(in2, t568); // Fp6 neg coeff 4/5 + let t575 = circuit_sub(in2, t569); // Fp6 neg coeff 5/5 + let t576 = circuit_add(t570, t536); // Fp6 add coeff 0/5 + let t577 = circuit_add(t571, t537); // Fp6 add coeff 1/5 + let t578 = circuit_add(t572, t562); // Fp6 add coeff 2/5 + let t579 = circuit_add(t573, t563); // Fp6 add coeff 3/5 + let t580 = circuit_add(t574, t548); // Fp6 add coeff 4/5 + let t581 = circuit_add(t575, t549); // Fp6 add coeff 5/5 + let t582 = circuit_add(t484, t485); + let t583 = circuit_mul(t582, in0); + let t584 = circuit_mul(t484, in1); + let t585 = circuit_sub(t584, t485); + let t586 = circuit_sub(t583, t584); + let t587 = circuit_sub(t586, t485); + let t588 = circuit_add(t585, t438); // Fp6 add coeff 0/5 + let t589 = circuit_add(t587, t439); // Fp6 add coeff 1/5 + let t590 = circuit_add(t472, t440); // Fp6 add coeff 2/5 + let t591 = circuit_add(t473, t441); // Fp6 add coeff 3/5 + let t592 = circuit_add(t498, t442); // Fp6 add coeff 4/5 + let t593 = circuit_add(t499, t443); // Fp6 add coeff 5/5 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = ( + t266, + t267, + t276, + t277, + t588, + t589, + t590, + t591, + t592, + t593, + t576, + t577, + t578, + t579, + t580, + t581, + ) + .new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0xa, 0x0, 0x0, 0x0]); // in0 + circuit_inputs = circuit_inputs.next_2([0x9, 0x0, 0x0, 0x0]); // in1 + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in2 + circuit_inputs = circuit_inputs.next_2([0x1, 0x0, 0x0, 0x0]); // in3 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(yInv_0); // in4 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in5 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in6 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in7 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in8 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in9 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.x0); // in10 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.x1); // in11 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.y0); // in12 + circuit_inputs = circuit_inputs.next_2(Q_or_Q_neg_0.y1); // in13 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a0); // in14 + circuit_inputs = circuit_inputs.next_2(M_i.c0b0a1); // in15 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a0); // in16 + circuit_inputs = circuit_inputs.next_2(M_i.c0b1a1); // in17 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a0); // in18 + circuit_inputs = circuit_inputs.next_2(M_i.c0b2a1); // in19 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a0); // in20 + circuit_inputs = circuit_inputs.next_2(M_i.c1b0a1); // in21 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a0); // in22 + circuit_inputs = circuit_inputs.next_2(M_i.c1b1a1); // in23 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a0); // in24 + circuit_inputs = circuit_inputs.next_2(M_i.c1b2a1); // in25 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Q0: G2Point = G2Point { + x0: outputs.get_output(t266), + x1: outputs.get_output(t267), + y0: outputs.get_output(t276), + y1: outputs.get_output(t277) + }; + let Mi_plus_one: E12T = E12T { + c0b0a0: outputs.get_output(t588), + c0b0a1: outputs.get_output(t589), + c0b1a0: outputs.get_output(t590), + c0b1a1: outputs.get_output(t591), + c0b2a0: outputs.get_output(t592), + c0b2a1: outputs.get_output(t593), + c1b0a0: outputs.get_output(t576), + c1b0a1: outputs.get_output(t577), + c1b1a0: outputs.get_output(t578), + c1b1a1: outputs.get_output(t579), + c1b2a0: outputs.get_output(t580), + c1b2a1: outputs.get_output(t581), + }; + return (Q0, Mi_plus_one); +} +#[inline(always)] +fn run_BN254_TOWER_MILLER_FINALIZE_BN_1P_circuit( + original_Q0: G2Point, yInv_0: u384, xNegOverY_0: u384, Q_0: G2Point, Mi: E12T +) -> (E12T,) { + // CONSTANT stack + let in0 = CE::> {}; // 0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d + let in1 = CE::> {}; // 0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2 + let in2 = CE::> {}; // 0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a + let in3 = CE::> {}; // 0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3 + let in4 = CE::> {}; // 0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48 + let in5 = CE::> {}; // 0x1 + let in6 = CE::> {}; // 0x0 + let in7 = CE::> {}; // 0xa + let in8 = CE::> {}; // 0x9 + + // INPUT stack + let (in9, in10, in11) = (CE::> {}, CE::> {}, CE::> {}); + let (in12, in13, in14) = (CE::> {}, CE::> {}, CE::> {}); + let (in15, in16, in17) = (CE::> {}, CE::> {}, CE::> {}); + let (in18, in19, in20) = (CE::> {}, CE::> {}, CE::> {}); + let (in21, in22, in23) = (CE::> {}, CE::> {}, CE::> {}); + let (in24, in25, in26) = (CE::> {}, CE::> {}, CE::> {}); + let (in27, in28, in29) = (CE::> {}, CE::> {}, CE::> {}); + let in30 = CE::> {}; + let t0 = circuit_sub(in6, in10); + let t1 = circuit_sub(in6, in12); + let t2 = circuit_mul(in9, in0); // Fp2 mul start + let t3 = circuit_mul(t0, in1); + let t4 = circuit_sub(t2, t3); // Fp2 mul real part end + let t5 = circuit_mul(in9, in1); + let t6 = circuit_mul(t0, in0); + let t7 = circuit_add(t5, t6); // Fp2 mul imag part end + let t8 = circuit_mul(in11, in2); // Fp2 mul start + let t9 = circuit_mul(t1, in3); + let t10 = circuit_sub(t8, t9); // Fp2 mul real part end + let t11 = circuit_mul(in11, in3); + let t12 = circuit_mul(t1, in2); + let t13 = circuit_add(t11, t12); // Fp2 mul imag part end + let t14 = circuit_mul(in9, in4); // Fp2 scalar mul coeff 0/1 + let t15 = circuit_mul(in10, in4); // Fp2 scalar mul coeff 1/1 + let t16 = circuit_mul(in11, in5); // Fp2 scalar mul coeff 0/1 + let t17 = circuit_mul(in12, in5); // Fp2 scalar mul coeff 1/1 + let t18 = circuit_sub(in17, t10); // Fp2 sub coeff 0/1 + let t19 = circuit_sub(in18, t13); // Fp2 sub coeff 1/1 + let t20 = circuit_sub(in15, t4); // Fp2 sub coeff 0/1 + let t21 = circuit_sub(in16, t7); // Fp2 sub coeff 1/1 + let t22 = circuit_mul(t20, t20); // Fp2 Inv start + let t23 = circuit_mul(t21, t21); + let t24 = circuit_add(t22, t23); + let t25 = circuit_inverse(t24); + let t26 = circuit_mul(t20, t25); // Fp2 Inv real part end + let t27 = circuit_mul(t21, t25); + let t28 = circuit_sub(in6, t27); // Fp2 Inv imag part end + let t29 = circuit_mul(t18, t26); // Fp2 mul start + let t30 = circuit_mul(t19, t28); + let t31 = circuit_sub(t29, t30); // Fp2 mul real part end + let t32 = circuit_mul(t18, t28); + let t33 = circuit_mul(t19, t26); + let t34 = circuit_add(t32, t33); // Fp2 mul imag part end + let t35 = circuit_add(t31, t34); + let t36 = circuit_sub(t31, t34); + let t37 = circuit_mul(t35, t36); + let t38 = circuit_mul(t31, t34); + let t39 = circuit_add(t38, t38); + let t40 = circuit_add(in15, t4); // Fp2 add coeff 0/1 + let t41 = circuit_add(in16, t7); // Fp2 add coeff 1/1 + let t42 = circuit_sub(t37, t40); // Fp2 sub coeff 0/1 + let t43 = circuit_sub(t39, t41); // Fp2 sub coeff 1/1 + let t44 = circuit_sub(in15, t42); // Fp2 sub coeff 0/1 + let t45 = circuit_sub(in16, t43); // Fp2 sub coeff 1/1 + let t46 = circuit_mul(t31, t44); // Fp2 mul start + let t47 = circuit_mul(t34, t45); + let t48 = circuit_sub(t46, t47); // Fp2 mul real part end + let t49 = circuit_mul(t31, t45); + let t50 = circuit_mul(t34, t44); + let t51 = circuit_add(t49, t50); // Fp2 mul imag part end + let t52 = circuit_sub(t48, in17); // Fp2 sub coeff 0/1 + let t53 = circuit_sub(t51, in18); // Fp2 sub coeff 1/1 + let t54 = circuit_mul(t31, in15); // Fp2 mul start + let t55 = circuit_mul(t34, in16); + let t56 = circuit_sub(t54, t55); // Fp2 mul real part end + let t57 = circuit_mul(t31, in16); + let t58 = circuit_mul(t34, in15); + let t59 = circuit_add(t57, t58); // Fp2 mul imag part end + let t60 = circuit_sub(t56, in17); // Fp2 sub coeff 0/1 + let t61 = circuit_sub(t59, in18); // Fp2 sub coeff 1/1 + let t62 = circuit_sub(t52, t16); // Fp2 sub coeff 0/1 + let t63 = circuit_sub(t53, t17); // Fp2 sub coeff 1/1 + let t64 = circuit_sub(t42, t14); // Fp2 sub coeff 0/1 + let t65 = circuit_sub(t43, t15); // Fp2 sub coeff 1/1 + let t66 = circuit_mul(t64, t64); // Fp2 Inv start + let t67 = circuit_mul(t65, t65); + let t68 = circuit_add(t66, t67); + let t69 = circuit_inverse(t68); + let t70 = circuit_mul(t64, t69); // Fp2 Inv real part end + let t71 = circuit_mul(t65, t69); + let t72 = circuit_sub(in6, t71); // Fp2 Inv imag part end + let t73 = circuit_mul(t62, t70); // Fp2 mul start + let t74 = circuit_mul(t63, t72); + let t75 = circuit_sub(t73, t74); // Fp2 mul real part end + let t76 = circuit_mul(t62, t72); + let t77 = circuit_mul(t63, t70); + let t78 = circuit_add(t76, t77); // Fp2 mul imag part end + let t79 = circuit_mul(t75, t42); // Fp2 mul start + let t80 = circuit_mul(t78, t43); + let t81 = circuit_sub(t79, t80); // Fp2 mul real part end + let t82 = circuit_mul(t75, t43); + let t83 = circuit_mul(t78, t42); + let t84 = circuit_add(t82, t83); // Fp2 mul imag part end + let t85 = circuit_sub(t81, t52); // Fp2 sub coeff 0/1 + let t86 = circuit_sub(t84, t53); // Fp2 sub coeff 1/1 + let t87 = circuit_mul(t31, in14); + let t88 = circuit_mul(t34, in14); + let t89 = circuit_mul(t60, in13); + let t90 = circuit_mul(t61, in13); + let t91 = circuit_mul(t75, in14); + let t92 = circuit_mul(t78, in14); + let t93 = circuit_mul(t85, in13); + let t94 = circuit_mul(t86, in13); + let t95 = circuit_mul(t91, t87); // Fp2 mul start + let t96 = circuit_mul(t92, t88); + let t97 = circuit_sub(t95, t96); // Fp2 mul real part end + let t98 = circuit_mul(t91, t88); + let t99 = circuit_mul(t92, t87); + let t100 = circuit_add(t98, t99); // Fp2 mul imag part end + let t101 = circuit_mul(t93, t89); // Fp2 mul start + let t102 = circuit_mul(t94, t90); + let t103 = circuit_sub(t101, t102); // Fp2 mul real part end + let t104 = circuit_mul(t93, t90); + let t105 = circuit_mul(t94, t89); + let t106 = circuit_add(t104, t105); // Fp2 mul imag part end + let t107 = circuit_add(t93, t89); // Fp2 add coeff 0/1 + let t108 = circuit_add(t94, t90); // Fp2 add coeff 1/1 + let t109 = circuit_add(t91, t87); // Fp2 add coeff 0/1 + let t110 = circuit_add(t92, t88); // Fp2 add coeff 1/1 + let t111 = circuit_add(t91, t93); // Fp2 add coeff 0/1 + let t112 = circuit_add(t92, t94); // Fp2 add coeff 1/1 + let t113 = circuit_add(t87, t89); // Fp2 add coeff 0/1 + let t114 = circuit_add(t88, t90); // Fp2 add coeff 1/1 + let t115 = circuit_mul(t113, t111); // Fp2 mul start + let t116 = circuit_mul(t114, t112); + let t117 = circuit_sub(t115, t116); // Fp2 mul real part end + let t118 = circuit_mul(t113, t112); + let t119 = circuit_mul(t114, t111); + let t120 = circuit_add(t118, t119); // Fp2 mul imag part end + let t121 = circuit_sub(t117, t97); // Fp2 sub coeff 0/1 + let t122 = circuit_sub(t120, t100); // Fp2 sub coeff 1/1 + let t123 = circuit_sub(t121, t103); // Fp2 sub coeff 0/1 + let t124 = circuit_sub(t122, t106); // Fp2 sub coeff 1/1 + let t125 = circuit_add(t103, t106); + let t126 = circuit_mul(t125, in7); + let t127 = circuit_mul(t103, in8); + let t128 = circuit_sub(t127, t106); + let t129 = circuit_sub(t126, t127); + let t130 = circuit_sub(t129, t106); + let t131 = circuit_add(t128, in5); + let t132 = circuit_add(in19, in25); // Fp6 add coeff 0/5 + let t133 = circuit_add(in20, in26); // Fp6 add coeff 1/5 + let t134 = circuit_add(in21, in27); // Fp6 add coeff 2/5 + let t135 = circuit_add(in22, in28); // Fp6 add coeff 3/5 + let t136 = circuit_add(in23, in29); // Fp6 add coeff 4/5 + let t137 = circuit_add(in24, in30); // Fp6 add coeff 5/5 + let t138 = circuit_add(t131, t109); // Fp6 add coeff 0/5 + let t139 = circuit_add(t130, t110); // Fp6 add coeff 1/5 + let t140 = circuit_add(t97, t107); // Fp6 add coeff 2/5 + let t141 = circuit_add(t100, t108); // Fp6 add coeff 3/5 + let t142 = circuit_add(t123, in6); // Fp6 add coeff 4/5 + let t143 = circuit_add(t124, in6); // Fp6 add coeff 5/5 + let t144 = circuit_mul(t132, t138); // Fp2 mul start + let t145 = circuit_mul(t133, t139); + let t146 = circuit_sub(t144, t145); // Fp2 mul real part end + let t147 = circuit_mul(t132, t139); + let t148 = circuit_mul(t133, t138); + let t149 = circuit_add(t147, t148); // Fp2 mul imag part end + let t150 = circuit_mul(t134, t140); // Fp2 mul start + let t151 = circuit_mul(t135, t141); + let t152 = circuit_sub(t150, t151); // Fp2 mul real part end + let t153 = circuit_mul(t134, t141); + let t154 = circuit_mul(t135, t140); + let t155 = circuit_add(t153, t154); // Fp2 mul imag part end + let t156 = circuit_mul(t136, t142); // Fp2 mul start + let t157 = circuit_mul(t137, t143); + let t158 = circuit_sub(t156, t157); // Fp2 mul real part end + let t159 = circuit_mul(t136, t143); + let t160 = circuit_mul(t137, t142); + let t161 = circuit_add(t159, t160); // Fp2 mul imag part end + let t162 = circuit_add(t134, t136); // Fp2 add coeff 0/1 + let t163 = circuit_add(t135, t137); // Fp2 add coeff 1/1 + let t164 = circuit_add(t140, t142); // Fp2 add coeff 0/1 + let t165 = circuit_add(t141, t143); // Fp2 add coeff 1/1 + let t166 = circuit_mul(t162, t164); // Fp2 mul start + let t167 = circuit_mul(t163, t165); + let t168 = circuit_sub(t166, t167); // Fp2 mul real part end + let t169 = circuit_mul(t162, t165); + let t170 = circuit_mul(t163, t164); + let t171 = circuit_add(t169, t170); // Fp2 mul imag part end + let t172 = circuit_sub(t168, t152); // Fp2 sub coeff 0/1 + let t173 = circuit_sub(t171, t155); // Fp2 sub coeff 1/1 + let t174 = circuit_sub(t172, t158); // Fp2 sub coeff 0/1 + let t175 = circuit_sub(t173, t161); // Fp2 sub coeff 1/1 + let t176 = circuit_add(t174, t175); + let t177 = circuit_mul(t176, in7); + let t178 = circuit_mul(t174, in8); + let t179 = circuit_sub(t178, t175); + let t180 = circuit_sub(t177, t178); + let t181 = circuit_sub(t180, t175); + let t182 = circuit_add(t179, t146); // Fp2 add coeff 0/1 + let t183 = circuit_add(t181, t149); // Fp2 add coeff 1/1 + let t184 = circuit_add(t132, t134); // Fp2 add coeff 0/1 + let t185 = circuit_add(t133, t135); // Fp2 add coeff 1/1 + let t186 = circuit_add(t138, t140); // Fp2 add coeff 0/1 + let t187 = circuit_add(t139, t141); // Fp2 add coeff 1/1 + let t188 = circuit_mul(t184, t186); // Fp2 mul start + let t189 = circuit_mul(t185, t187); + let t190 = circuit_sub(t188, t189); // Fp2 mul real part end + let t191 = circuit_mul(t184, t187); + let t192 = circuit_mul(t185, t186); + let t193 = circuit_add(t191, t192); // Fp2 mul imag part end + let t194 = circuit_sub(t190, t146); // Fp2 sub coeff 0/1 + let t195 = circuit_sub(t193, t149); // Fp2 sub coeff 1/1 + let t196 = circuit_sub(t194, t152); // Fp2 sub coeff 0/1 + let t197 = circuit_sub(t195, t155); // Fp2 sub coeff 1/1 + let t198 = circuit_add(t158, t161); + let t199 = circuit_mul(t198, in7); + let t200 = circuit_mul(t158, in8); + let t201 = circuit_sub(t200, t161); + let t202 = circuit_sub(t199, t200); + let t203 = circuit_sub(t202, t161); + let t204 = circuit_add(t196, t201); // Fp2 add coeff 0/1 + let t205 = circuit_add(t197, t203); // Fp2 add coeff 1/1 + let t206 = circuit_add(t132, t136); // Fp2 add coeff 0/1 + let t207 = circuit_add(t133, t137); // Fp2 add coeff 1/1 + let t208 = circuit_add(t138, t142); // Fp2 add coeff 0/1 + let t209 = circuit_add(t139, t143); // Fp2 add coeff 1/1 + let t210 = circuit_mul(t208, t206); // Fp2 mul start + let t211 = circuit_mul(t209, t207); + let t212 = circuit_sub(t210, t211); // Fp2 mul real part end + let t213 = circuit_mul(t208, t207); + let t214 = circuit_mul(t209, t206); + let t215 = circuit_add(t213, t214); // Fp2 mul imag part end + let t216 = circuit_sub(t212, t146); // Fp2 sub coeff 0/1 + let t217 = circuit_sub(t215, t149); // Fp2 sub coeff 1/1 + let t218 = circuit_sub(t216, t158); // Fp2 sub coeff 0/1 + let t219 = circuit_sub(t217, t161); // Fp2 sub coeff 1/1 + let t220 = circuit_add(t218, t152); // Fp2 add coeff 0/1 + let t221 = circuit_add(t219, t155); // Fp2 add coeff 1/1 + let t222 = circuit_mul(in19, t131); // Fp2 mul start + let t223 = circuit_mul(in20, t130); + let t224 = circuit_sub(t222, t223); // Fp2 mul real part end + let t225 = circuit_mul(in19, t130); + let t226 = circuit_mul(in20, t131); + let t227 = circuit_add(t225, t226); // Fp2 mul imag part end + let t228 = circuit_mul(in21, t97); // Fp2 mul start + let t229 = circuit_mul(in22, t100); + let t230 = circuit_sub(t228, t229); // Fp2 mul real part end + let t231 = circuit_mul(in21, t100); + let t232 = circuit_mul(in22, t97); + let t233 = circuit_add(t231, t232); // Fp2 mul imag part end + let t234 = circuit_mul(in23, t123); // Fp2 mul start + let t235 = circuit_mul(in24, t124); + let t236 = circuit_sub(t234, t235); // Fp2 mul real part end + let t237 = circuit_mul(in23, t124); + let t238 = circuit_mul(in24, t123); + let t239 = circuit_add(t237, t238); // Fp2 mul imag part end + let t240 = circuit_add(in21, in23); // Fp2 add coeff 0/1 + let t241 = circuit_add(in22, in24); // Fp2 add coeff 1/1 + let t242 = circuit_add(t97, t123); // Fp2 add coeff 0/1 + let t243 = circuit_add(t100, t124); // Fp2 add coeff 1/1 + let t244 = circuit_mul(t240, t242); // Fp2 mul start + let t245 = circuit_mul(t241, t243); + let t246 = circuit_sub(t244, t245); // Fp2 mul real part end + let t247 = circuit_mul(t240, t243); + let t248 = circuit_mul(t241, t242); + let t249 = circuit_add(t247, t248); // Fp2 mul imag part end + let t250 = circuit_sub(t246, t230); // Fp2 sub coeff 0/1 + let t251 = circuit_sub(t249, t233); // Fp2 sub coeff 1/1 + let t252 = circuit_sub(t250, t236); // Fp2 sub coeff 0/1 + let t253 = circuit_sub(t251, t239); // Fp2 sub coeff 1/1 + let t254 = circuit_add(t252, t253); + let t255 = circuit_mul(t254, in7); + let t256 = circuit_mul(t252, in8); + let t257 = circuit_sub(t256, t253); + let t258 = circuit_sub(t255, t256); + let t259 = circuit_sub(t258, t253); + let t260 = circuit_add(t257, t224); // Fp2 add coeff 0/1 + let t261 = circuit_add(t259, t227); // Fp2 add coeff 1/1 + let t262 = circuit_add(in19, in21); // Fp2 add coeff 0/1 + let t263 = circuit_add(in20, in22); // Fp2 add coeff 1/1 + let t264 = circuit_add(t131, t97); // Fp2 add coeff 0/1 + let t265 = circuit_add(t130, t100); // Fp2 add coeff 1/1 + let t266 = circuit_mul(t262, t264); // Fp2 mul start + let t267 = circuit_mul(t263, t265); + let t268 = circuit_sub(t266, t267); // Fp2 mul real part end + let t269 = circuit_mul(t262, t265); + let t270 = circuit_mul(t263, t264); + let t271 = circuit_add(t269, t270); // Fp2 mul imag part end + let t272 = circuit_sub(t268, t224); // Fp2 sub coeff 0/1 + let t273 = circuit_sub(t271, t227); // Fp2 sub coeff 1/1 + let t274 = circuit_sub(t272, t230); // Fp2 sub coeff 0/1 + let t275 = circuit_sub(t273, t233); // Fp2 sub coeff 1/1 + let t276 = circuit_add(t236, t239); + let t277 = circuit_mul(t276, in7); + let t278 = circuit_mul(t236, in8); + let t279 = circuit_sub(t278, t239); + let t280 = circuit_sub(t277, t278); + let t281 = circuit_sub(t280, t239); + let t282 = circuit_add(t274, t279); // Fp2 add coeff 0/1 + let t283 = circuit_add(t275, t281); // Fp2 add coeff 1/1 + let t284 = circuit_add(in19, in23); // Fp2 add coeff 0/1 + let t285 = circuit_add(in20, in24); // Fp2 add coeff 1/1 + let t286 = circuit_add(t131, t123); // Fp2 add coeff 0/1 + let t287 = circuit_add(t130, t124); // Fp2 add coeff 1/1 + let t288 = circuit_mul(t286, t284); // Fp2 mul start + let t289 = circuit_mul(t287, t285); + let t290 = circuit_sub(t288, t289); // Fp2 mul real part end + let t291 = circuit_mul(t286, t285); + let t292 = circuit_mul(t287, t284); + let t293 = circuit_add(t291, t292); // Fp2 mul imag part end + let t294 = circuit_sub(t290, t224); // Fp2 sub coeff 0/1 + let t295 = circuit_sub(t293, t227); // Fp2 sub coeff 1/1 + let t296 = circuit_sub(t294, t236); // Fp2 sub coeff 0/1 + let t297 = circuit_sub(t295, t239); // Fp2 sub coeff 1/1 + let t298 = circuit_add(t296, t230); // Fp2 add coeff 0/1 + let t299 = circuit_add(t297, t233); // Fp2 add coeff 1/1 + let t300 = circuit_mul(in25, t109); // Fp2 mul start + let t301 = circuit_mul(in26, t110); + let t302 = circuit_sub(t300, t301); // Fp2 mul real part end + let t303 = circuit_mul(in25, t110); + let t304 = circuit_mul(in26, t109); + let t305 = circuit_add(t303, t304); // Fp2 mul imag part end + let t306 = circuit_mul(in27, t107); // Fp2 mul start + let t307 = circuit_mul(in28, t108); + let t308 = circuit_sub(t306, t307); // Fp2 mul real part end + let t309 = circuit_mul(in27, t108); + let t310 = circuit_mul(in28, t107); + let t311 = circuit_add(t309, t310); // Fp2 mul imag part end + let t312 = circuit_mul(in29, in6); // Fp2 mul start + let t313 = circuit_mul(in30, in6); + let t314 = circuit_sub(t312, t313); // Fp2 mul real part end + let t315 = circuit_mul(in29, in6); + let t316 = circuit_mul(in30, in6); + let t317 = circuit_add(t315, t316); // Fp2 mul imag part end + let t318 = circuit_add(in27, in29); // Fp2 add coeff 0/1 + let t319 = circuit_add(in28, in30); // Fp2 add coeff 1/1 + let t320 = circuit_add(t107, in6); // Fp2 add coeff 0/1 + let t321 = circuit_add(t108, in6); // Fp2 add coeff 1/1 + let t322 = circuit_mul(t318, t320); // Fp2 mul start + let t323 = circuit_mul(t319, t321); + let t324 = circuit_sub(t322, t323); // Fp2 mul real part end + let t325 = circuit_mul(t318, t321); + let t326 = circuit_mul(t319, t320); + let t327 = circuit_add(t325, t326); // Fp2 mul imag part end + let t328 = circuit_sub(t324, t308); // Fp2 sub coeff 0/1 + let t329 = circuit_sub(t327, t311); // Fp2 sub coeff 1/1 + let t330 = circuit_sub(t328, t314); // Fp2 sub coeff 0/1 + let t331 = circuit_sub(t329, t317); // Fp2 sub coeff 1/1 + let t332 = circuit_add(t330, t331); + let t333 = circuit_mul(t332, in7); + let t334 = circuit_mul(t330, in8); + let t335 = circuit_sub(t334, t331); + let t336 = circuit_sub(t333, t334); + let t337 = circuit_sub(t336, t331); + let t338 = circuit_add(t335, t302); // Fp2 add coeff 0/1 + let t339 = circuit_add(t337, t305); // Fp2 add coeff 1/1 + let t340 = circuit_add(in25, in27); // Fp2 add coeff 0/1 + let t341 = circuit_add(in26, in28); // Fp2 add coeff 1/1 + let t342 = circuit_add(t109, t107); // Fp2 add coeff 0/1 + let t343 = circuit_add(t110, t108); // Fp2 add coeff 1/1 + let t344 = circuit_mul(t340, t342); // Fp2 mul start + let t345 = circuit_mul(t341, t343); + let t346 = circuit_sub(t344, t345); // Fp2 mul real part end + let t347 = circuit_mul(t340, t343); + let t348 = circuit_mul(t341, t342); + let t349 = circuit_add(t347, t348); // Fp2 mul imag part end + let t350 = circuit_sub(t346, t302); // Fp2 sub coeff 0/1 + let t351 = circuit_sub(t349, t305); // Fp2 sub coeff 1/1 + let t352 = circuit_sub(t350, t308); // Fp2 sub coeff 0/1 + let t353 = circuit_sub(t351, t311); // Fp2 sub coeff 1/1 + let t354 = circuit_add(t314, t317); + let t355 = circuit_mul(t354, in7); + let t356 = circuit_mul(t314, in8); + let t357 = circuit_sub(t356, t317); + let t358 = circuit_sub(t355, t356); + let t359 = circuit_sub(t358, t317); + let t360 = circuit_add(t352, t357); // Fp2 add coeff 0/1 + let t361 = circuit_add(t353, t359); // Fp2 add coeff 1/1 + let t362 = circuit_add(in25, in29); // Fp2 add coeff 0/1 + let t363 = circuit_add(in26, in30); // Fp2 add coeff 1/1 + let t364 = circuit_add(t109, in6); // Fp2 add coeff 0/1 + let t365 = circuit_add(t110, in6); // Fp2 add coeff 1/1 + let t366 = circuit_mul(t364, t362); // Fp2 mul start + let t367 = circuit_mul(t365, t363); + let t368 = circuit_sub(t366, t367); // Fp2 mul real part end + let t369 = circuit_mul(t364, t363); + let t370 = circuit_mul(t365, t362); + let t371 = circuit_add(t369, t370); // Fp2 mul imag part end + let t372 = circuit_sub(t368, t302); // Fp2 sub coeff 0/1 + let t373 = circuit_sub(t371, t305); // Fp2 sub coeff 1/1 + let t374 = circuit_sub(t372, t314); // Fp2 sub coeff 0/1 + let t375 = circuit_sub(t373, t317); // Fp2 sub coeff 1/1 + let t376 = circuit_add(t374, t308); // Fp2 add coeff 0/1 + let t377 = circuit_add(t375, t311); // Fp2 add coeff 1/1 + let t378 = circuit_sub(t182, t260); // Fp6 sub coeff 0/5 + let t379 = circuit_sub(t183, t261); // Fp6 sub coeff 1/5 + let t380 = circuit_sub(t204, t282); // Fp6 sub coeff 2/5 + let t381 = circuit_sub(t205, t283); // Fp6 sub coeff 3/5 + let t382 = circuit_sub(t220, t298); // Fp6 sub coeff 4/5 + let t383 = circuit_sub(t221, t299); // Fp6 sub coeff 5/5 + let t384 = circuit_sub(t378, t338); // Fp6 sub coeff 0/5 + let t385 = circuit_sub(t379, t339); // Fp6 sub coeff 1/5 + let t386 = circuit_sub(t380, t360); // Fp6 sub coeff 2/5 + let t387 = circuit_sub(t381, t361); // Fp6 sub coeff 3/5 + let t388 = circuit_sub(t382, t376); // Fp6 sub coeff 4/5 + let t389 = circuit_sub(t383, t377); // Fp6 sub coeff 5/5 + let t390 = circuit_add(t376, t377); + let t391 = circuit_mul(t390, in7); + let t392 = circuit_mul(t376, in8); + let t393 = circuit_sub(t392, t377); + let t394 = circuit_sub(t391, t392); + let t395 = circuit_sub(t394, t377); + let t396 = circuit_add(t393, t260); // Fp6 add coeff 0/5 + let t397 = circuit_add(t395, t261); // Fp6 add coeff 1/5 + let t398 = circuit_add(t338, t282); // Fp6 add coeff 2/5 + let t399 = circuit_add(t339, t283); // Fp6 add coeff 3/5 + let t400 = circuit_add(t360, t298); // Fp6 add coeff 4/5 + let t401 = circuit_add(t361, t299); // Fp6 add coeff 5/5 + + let modulus = get_BN254_modulus(); // BN254 prime field modulus + + let mut circuit_inputs = ( + t396, t397, t398, t399, t400, t401, t384, t385, t386, t387, t388, t389, + ) + .new_inputs(); + // Prefill constants: + + circuit_inputs = circuit_inputs + .next_span(TOWER_MILLER_FINALIZE_BN_1P_BN254_CONSTANTS.span()); // in0 - in8 + + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(original_Q0.x0); // in9 + circuit_inputs = circuit_inputs.next_2(original_Q0.x1); // in10 + circuit_inputs = circuit_inputs.next_2(original_Q0.y0); // in11 + circuit_inputs = circuit_inputs.next_2(original_Q0.y1); // in12 + circuit_inputs = circuit_inputs.next_2(yInv_0); // in13 + circuit_inputs = circuit_inputs.next_2(xNegOverY_0); // in14 + circuit_inputs = circuit_inputs.next_2(Q_0.x0); // in15 + circuit_inputs = circuit_inputs.next_2(Q_0.x1); // in16 + circuit_inputs = circuit_inputs.next_2(Q_0.y0); // in17 + circuit_inputs = circuit_inputs.next_2(Q_0.y1); // in18 + circuit_inputs = circuit_inputs.next_2(Mi.c0b0a0); // in19 + circuit_inputs = circuit_inputs.next_2(Mi.c0b0a1); // in20 + circuit_inputs = circuit_inputs.next_2(Mi.c0b1a0); // in21 + circuit_inputs = circuit_inputs.next_2(Mi.c0b1a1); // in22 + circuit_inputs = circuit_inputs.next_2(Mi.c0b2a0); // in23 + circuit_inputs = circuit_inputs.next_2(Mi.c0b2a1); // in24 + circuit_inputs = circuit_inputs.next_2(Mi.c1b0a0); // in25 + circuit_inputs = circuit_inputs.next_2(Mi.c1b0a1); // in26 + circuit_inputs = circuit_inputs.next_2(Mi.c1b1a0); // in27 + circuit_inputs = circuit_inputs.next_2(Mi.c1b1a1); // in28 + circuit_inputs = circuit_inputs.next_2(Mi.c1b2a0); // in29 + circuit_inputs = circuit_inputs.next_2(Mi.c1b2a1); // in30 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let Mi: E12T = E12T { + c0b0a0: outputs.get_output(t396), + c0b0a1: outputs.get_output(t397), + c0b1a0: outputs.get_output(t398), + c0b1a1: outputs.get_output(t399), + c0b2a0: outputs.get_output(t400), + c0b2a1: outputs.get_output(t401), + c1b0a0: outputs.get_output(t384), + c1b0a1: outputs.get_output(t385), + c1b1a0: outputs.get_output(t386), + c1b1a1: outputs.get_output(t387), + c1b2a0: outputs.get_output(t388), + c1b2a1: outputs.get_output(t389), + }; + return (Mi,); +} +const TOWER_MILLER_FINALIZE_BN_1P_BN254_CONSTANTS: [ + u384 + ; 9] = [ + u384 { + limb0: 0xc2c3330c99e39557176f553d, + limb1: 0x4c0bec3cf559b143b78cc310, + limb2: 0x2fb347984f7911f7, + limb3: 0x0 + }, + u384 { + limb0: 0xb7c9dce1665d51c640fcba2, + limb1: 0x4ba4cc8bd75a079432ae2a1d, + limb2: 0x16c9e55061ebae20, + limb3: 0x0 + }, + u384 { + limb0: 0xa9c95998dc54014671a0135a, + limb1: 0xdc5ec698b6e2f9b9dbaae0ed, + limb2: 0x63cf305489af5dc, + limb3: 0x0 + }, + u384 { + limb0: 0x8fa25bd282d37f632623b0e3, + limb1: 0x704b5a7ec796f2b21807dc9, + limb2: 0x7c03cbcac41049a, + limb3: 0x0 + }, + u384 { + limb0: 0xbb966e3de4bd44e5607cfd48, + limb1: 0x5e6dd9e7e0acccb0c28f069f, + limb2: 0x30644e72e131a029, + limb3: 0x0 + }, + u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { limb0: 0xa, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + u384 { limb0: 0x9, limb1: 0x0, limb2: 0x0, limb3: 0x0 } +]; +#[inline(always)] +fn run_FP6_NEG_circuit( + b0a0: u384, b0a1: u384, b1a0: u384, b1a1: u384, b2a0: u384, b2a1: u384, curve_index: usize +) -> (u384, u384, u384, u384, u384, u384) { + // CONSTANT stack + let in0 = CE::> {}; // 0x0 + + // INPUT stack + let (in1, in2, in3) = (CE::> {}, CE::> {}, CE::> {}); + let (in4, in5, in6) = (CE::> {}, CE::> {}, CE::> {}); + let t0 = circuit_sub(in0, in1); + let t1 = circuit_sub(in0, in2); + let t2 = circuit_sub(in0, in3); + let t3 = circuit_sub(in0, in4); + let t4 = circuit_sub(in0, in5); + let t5 = circuit_sub(in0, in6); + + let modulus = get_p(curve_index); + let modulus = TryInto::< + _, CircuitModulus + >::try_into([modulus.limb0, modulus.limb1, modulus.limb2, modulus.limb3]) + .unwrap(); + + let mut circuit_inputs = (t0, t1, t2, t3, t4, t5,).new_inputs(); + // Prefill constants: + circuit_inputs = circuit_inputs.next_2([0x0, 0x0, 0x0, 0x0]); // in0 + // Fill inputs: + circuit_inputs = circuit_inputs.next_2(b0a0); // in1 + circuit_inputs = circuit_inputs.next_2(b0a1); // in2 + circuit_inputs = circuit_inputs.next_2(b1a0); // in3 + circuit_inputs = circuit_inputs.next_2(b1a1); // in4 + circuit_inputs = circuit_inputs.next_2(b2a0); // in5 + circuit_inputs = circuit_inputs.next_2(b2a1); // in6 + + let outputs = circuit_inputs.done_2().eval(modulus).unwrap(); + let r0: u384 = outputs.get_output(t0); + let r1: u384 = outputs.get_output(t1); + let r2: u384 = outputs.get_output(t2); + let r3: u384 = outputs.get_output(t3); + let r4: u384 = outputs.get_output(t4); + let r5: u384 = outputs.get_output(t5); + return (r0, r1, r2, r3, r4, r5); +} + +#[cfg(test)] +mod tests { + use core::traits::TryInto; + + use core::circuit::{ + RangeCheck96, AddMod, MulMod, u96, CircuitElement, CircuitInput, circuit_add, circuit_sub, + circuit_mul, circuit_inverse, EvalCircuitResult, EvalCircuitTrait, u384, + CircuitOutputsTrait, CircuitModulus, AddInputResultTrait, CircuitInputs + }; + use garaga::definitions::{ + G1Point, G2Point, E12D, E12DMulQuotient, G1G2Pair, BNProcessedPair, BLSProcessedPair, + MillerLoopResultScalingFactor, G2Line + }; + use garaga::ec_ops::{SlopeInterceptOutput, FunctionFeltEvaluations, FunctionFelt}; + + use super::{ + run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit, + run_BLS12_381_E12T_CYCLO_SQUARE_COMPRESSED_circuit, + run_BLS12_381_E12T_DECOMP_KARABINA_II_circuit, + run_BLS12_381_E12T_DECOMP_KARABINA_I_NZ_circuit, + run_BLS12_381_E12T_DECOMP_KARABINA_I_Z_circuit, run_BLS12_381_E12T_FROBENIUS_CUBE_circuit, + run_BLS12_381_E12T_FROBENIUS_SQUARE_circuit, run_BLS12_381_E12T_FROBENIUS_circuit, + run_BLS12_381_E12T_INVERSE_circuit, run_BLS12_381_E12T_MUL_circuit, + run_BLS12_381_TOWER_MILLER_BIT0_1P_circuit, run_BLS12_381_TOWER_MILLER_BIT1_1P_circuit, + run_BLS12_381_TOWER_MILLER_INIT_BIT_1P_circuit, run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit, + run_BN254_E12T_FROBENIUS_CUBE_circuit, run_BN254_E12T_FROBENIUS_SQUARE_circuit, + run_BN254_E12T_FROBENIUS_circuit, run_BN254_E12T_INVERSE_circuit, + run_BN254_E12T_MUL_circuit, run_BN254_TOWER_MILLER_BIT0_1P_circuit, + run_BN254_TOWER_MILLER_BIT1_1P_circuit, run_BN254_TOWER_MILLER_FINALIZE_BN_1P_circuit, + run_FP6_NEG_circuit + }; +} diff --git a/src/src/core/circuit.cairo b/src/src/core/circuit.cairo index 7e29c997..713cd87e 100644 --- a/src/src/core/circuit.cairo +++ b/src/src/core/circuit.cairo @@ -1,17 +1,29 @@ use core::circuit::{ add_circuit_input, AddInputResult, CircuitData, IntoCircuitInputValue, CircuitDefinition, - init_circuit_data, CircuitInputAccumulator, into_u96_guarantee + init_circuit_data, CircuitInputAccumulator, into_u96_guarantee, U96Guarantee }; use core::panic_with_felt252; use garaga::definitions::{E12D, G2Line, u384, u288}; use garaga::utils::hashing::{hades_permutation, PoseidonState}; -use core::panics::panic; +// use core::panics::panic; + +impl u288IntoCircuitInputValue of IntoCircuitInputValue { + fn into_circuit_input_value(self: u288) -> [U96Guarantee; 4] { + [ + into_u96_guarantee(self.limb0), + into_u96_guarantee(self.limb1), + into_u96_guarantee(self.limb2), + into_u96_guarantee(0_u8), + ] + } +} + #[generate_trait] pub impl AddInputResultImpl2 of AddInputResultTrait2 { /// Adds an input to the accumulator. // Inlining to make sure possibly huge `C` won't be in a user function name. - // #[inline] + #[inline] fn next_2, +Drop>( self: AddInputResult, value: Value ) -> AddInputResult { diff --git a/src/src/definitions.cairo b/src/src/definitions.cairo index 877b1db0..a3bc38fc 100644 --- a/src/src/definitions.cairo +++ b/src/src/definitions.cairo @@ -1,4 +1,4 @@ -use core::circuit::{u96, u384, CircuitModulus}; +use core::circuit::{u96, u384, U384Zero, CircuitModulus}; use garaga::basic_field_ops::{neg_mod_p}; use core::result::Result; use core::serde::{Serde}; @@ -103,16 +103,16 @@ impl G1PointZero of num::traits::Zero { } } -impl U384One of num::traits::One { - fn one() -> u384 { - u384 { limb0: 1, limb1: 0, limb2: 0, limb3: 0 } +// Represents the point at infinity +impl G2PointZero of num::traits::Zero { + fn zero() -> G2Point { + G2Point { x0: Zero::zero(), x1: Zero::zero(), y0: Zero::zero(), y1: Zero::zero() } } - - fn is_one(self: @u384) -> bool { - *self == Self::one() + fn is_zero(self: @G2Point) -> bool { + *self == Self::zero() } - fn is_non_one(self: @u384) -> bool { - !self.is_one() + fn is_non_zero(self: @G2Point) -> bool { + !self.is_zero() } } @@ -142,6 +142,18 @@ impl U288One of num::traits::One { } +impl U384One of num::traits::One { + fn one() -> u384 { + u384 { limb0: 1, limb1: 0, limb2: 0, limb3: 0 } + } + fn is_one(self: @u384) -> bool { + *self == Self::one() + } + fn is_non_one(self: @u384) -> bool { + !self.is_one() + } +} + impl E12DOneU384 of num::traits::One> { fn one() -> E12D { E12D { @@ -953,6 +965,35 @@ const ED25519: Curve = }, }; +const BLS_G2_GENERATOR: G2Point = + G2Point { + x0: u384 { + limb0: 0xa805bbefd48056c8c121bdb8, + limb1: 0xb4510b647ae3d1770bac0326, + limb2: 0x2dc51051c6e47ad4fa403b02, + limb3: 0x24aa2b2f08f0a9126080527 + }, + x1: u384 { + limb0: 0x13945d57e5ac7d055d042b7e, + limb1: 0xb5da61bbdc7f5049334cf112, + limb2: 0x88274f65596bd0d09920b61a, + limb3: 0x13e02b6052719f607dacd3a0 + }, + y0: u384 { + limb0: 0x3baca289e193548608b82801, + limb1: 0x6d429a695160d12c923ac9cc, + limb2: 0xda2e351aadfd9baa8cbdd3a7, + limb3: 0xce5d527727d6e118cc9cdc6 + }, + y1: u384 { + limb0: 0x5cec1da1aaa9075ff05f79be, + limb1: 0x267492ab572e99ab3f370d27, + limb2: 0x2bc28b99cb3e287e85a763af, + limb3: 0x606c4a02ea734cc32acd2b0 + } + }; + + // jy00(6 * 0x44E992B44A6909F1 + 2)[2:] with consecutive zeros replaced by 3, and -1 replaced by 2 const bn_bits: [ felt252 diff --git a/src/src/ec_ops.cairo b/src/src/ec_ops.cairo index c8f12a49..97fc68b6 100644 --- a/src/src/ec_ops.cairo +++ b/src/src/ec_ops.cairo @@ -74,19 +74,6 @@ impl G1PointImpl of G1PointTrait { } } -#[generate_trait] -impl G2PointImpl of G2PointTrait { - fn assert_on_curve(self: @G2Point, curve_index: usize) { - let (b20, b21) = get_b2(curve_index).unwrap(); - let (check0, check1) = ec::run_IS_ON_CURVE_G2_circuit( - *self, get_a(curve_index), b20, b21, curve_index - ); - u384_assert_zero(check0); - u384_assert_zero(check1); - } -} - - // Adds two elliptic curve points on a given curve. // Does not check the input points are on the curve. fn ec_safe_add(p: G1Point, q: G1Point, curve_index: usize) -> G1Point { diff --git a/src/src/ec_ops_g2.cairo b/src/src/ec_ops_g2.cairo new file mode 100644 index 00000000..1067da0b --- /dev/null +++ b/src/src/ec_ops_g2.cairo @@ -0,0 +1,318 @@ +use core::circuit::CircuitElement as CE; +use core::circuit::CircuitInput as CI; + +use core::circuit::{ + u384, circuit_add, circuit_sub, circuit_mul, circuit_inverse, EvalCircuitTrait, + CircuitOutputsTrait, CircuitModulus, CircuitInputs +}; +use core::option::Option; +use garaga::core::circuit::AddInputResultTrait2; +use garaga::definitions::{G2Point, G2PointZero, get_BLS12_381_modulus, get_b2, get_a}; +use garaga::circuits::ec; +use garaga::utils::u384_assert_zero; + + +#[generate_trait] +impl G2PointImpl of G2PointTrait { + fn assert_on_curve(self: @G2Point, curve_index: usize) { + let (b20, b21) = get_b2(curve_index).unwrap(); + let (check0, check1) = ec::run_IS_ON_CURVE_G2_circuit( + *self, get_a(curve_index), b20, b21, curve_index + ); + u384_assert_zero(check0); + u384_assert_zero(check1); + } + fn is_on_curve(self: @G2Point, curve_index: usize) -> bool { + let (b20, b21) = get_b2(curve_index).unwrap(); + let (check0, check1) = ec::run_IS_ON_CURVE_G2_circuit( + *self, get_a(curve_index), b20, b21, curve_index + ); + return check0.is_zero() && check1.is_zero(); + } +} + +// G2 Ops for BLS12-381. + +// Returns Option::None in case of error. +fn ec_mul(pt: G2Point, s: u256, curve_index: usize) -> Option { + if pt.is_zero() { + // Input point is at infinity, return it + return Option::Some(pt); + } else { + // Point is not at infinity + if pt.is_on_curve(curve_index) { + if s == 0 { + return Option::Some(G2PointZero::zero()); + } else if s == 1 { + return Option::Some(pt); + } else { + // Point is on the curve. + // s is >= 2. + let bits = get_bits_little(s); + let pt = ec_mul_inner(pt, bits, curve_index); + match pt { + Option::Some(r) => Option::Some(r), + Option::None => Option::Some(G2PointZero::zero()), + } + } + } else { + // Point is not on the curve + return Option::None; + } + } +} + +// Returns the bits of the 256 bit number in little endian format. +fn get_bits_little(s: u256) -> Array { + let mut bits = ArrayTrait::new(); + let mut s_low = s.low; + while s_low != 0 { + let (q, r) = core::traits::DivRem::div_rem(s_low, 2); + bits.append(r.into()); + s_low = q; + }; + let mut s_high = s.high; + if s_high != 0 { + while bits.len() != 128 { + bits.append(0); + } + } + while s_high != 0 { + let (q, r) = core::traits::DivRem::div_rem(s_high, 2); + bits.append(r.into()); + s_high = q; + }; + bits +} + +#[inline] +fn ec_safe_add(P: G2Point, Q: G2Point, curve_index: usize) -> Option { + // assumes that the points are on the curve and not the point at infinity. + // Returns None if the points are the same and opposite y coordinates (Point at infinity) + let same_x = eq_mod_p(P.x0, P.x1, Q.x0, Q.x1); + + if same_x { + let opposite_y = eq_neg_mod_p(P.y0, P.y1, Q.y0, Q.y1); + + if opposite_y { + return Option::None; + } else { + let (R) = ec::run_DOUBLE_EC_POINT_G2_A_EQ_0_circuit(P, curve_index); + return Option::Some(R); + } + } else { + let (R) = ec::run_ADD_EC_POINTS_G2_circuit(P, Q, curve_index); + return Option::Some(R); + } +} +// Should not be called outside of ec_mul. +// Returns Option::None in case of point at infinity. +// The size of bits array must be at minimum 2 and the point must be on the curve. +fn ec_mul_inner(pt: G2Point, mut bits: Array, curve_index: usize) -> Option { + let mut temp = pt; + let mut result: Option = Option::None; + for bit in bits { + if bit != 0 { + match result { + Option::Some(R) => result = ec_safe_add(temp, R, curve_index), + Option::None => result = Option::Some(temp), + }; + }; + let (_temp) = ec::run_DOUBLE_EC_POINT_G2_A_EQ_0_circuit(temp, curve_index); + temp = _temp; + }; + + return result; +} + + +// returns true if a == b mod p bls12-381 +#[inline] +pub fn eq_mod_p(a0: u384, a1: u384, b0: u384, b1: u384) -> bool { + let _a0 = CE::> {}; + let _a1 = CE::> {}; + let _b0 = CE::> {}; + let _b1 = CE::> {}; + let sub0 = circuit_sub(_a0, _b0); + let sub1 = circuit_sub(_a1, _b1); + + let modulus = get_BLS12_381_modulus(); + + let outputs = (sub0, sub1) + .new_inputs() + .next_2(a0) + .next_2(a1) + .next_2(b0) + .next_2(b1) + .done_2() + .eval(modulus) + .unwrap(); + + return outputs.get_output(sub0).is_zero() && outputs.get_output(sub1).is_zero(); +} + +// returns true if a == -b mod p bls12-381 +#[inline] +pub fn eq_neg_mod_p(a0: u384, a1: u384, b0: u384, b1: u384) -> bool { + let _a0 = CE::> {}; + let _a1 = CE::> {}; + let _b0 = CE::> {}; + let _b1 = CE::> {}; + let check0 = circuit_add(_a0, _b0); + let check1 = circuit_add(_a1, _b1); + + let modulus = get_BLS12_381_modulus(); + let outputs = (check0, check1) + .new_inputs() + .next_2(a0) + .next_2(a1) + .next_2(b0) + .next_2(b1) + .done_2() + .eval(modulus) + .unwrap(); + + return outputs.get_output(check0).is_zero() && outputs.get_output(check1).is_zero(); +} + + +#[cfg(test)] +mod tests { + use super::{eq_mod_p, eq_neg_mod_p, G2Point, G2PointZero, ec_safe_add, u384, ec_mul}; + use garaga::definitions::BLS_G2_GENERATOR; + #[test] + fn test_ec_mul_g2() { + let g = BLS_G2_GENERATOR; + + let s = 0; + let curve_index = 1; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == G2PointZero::zero()); + + let s: u256 = 1; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == g); + + let s: u256 = 2; + let g2: G2Point = G2Point { + x0: u384 { + limb0: 0xf3611b78c952aacab827a053, + limb1: 0xe1ea1e1e4d00dbae81f14b0b, + limb2: 0xcc7ed5863bc0b995b8825e0e, + limb3: 0x1638533957d540a9d2370f17 + }, + x1: u384 { + limb0: 0xb57ec72a6178288c47c33577, + limb1: 0x728114d1031e1572c6c886f6, + limb2: 0x730a124fd70662a904ba1074, + limb3: 0xa4edef9c1ed7f729f520e47 + }, + y0: u384 { + limb0: 0x764bf3bd999d95d71e4c9899, + limb1: 0xbfe6bd221e47aa8ae88dece9, + limb2: 0x2b5256789a66da69bf91009c, + limb3: 0x468fb440d82b0630aeb8dca + }, + y1: u384 { + limb0: 0xa59c8967acdefd8b6e36ccf3, + limb1: 0x97003f7a13c308f5422e1aa0, + limb2: 0x3f887136a43253d9c66c4116, + limb3: 0xf6d4552fa65dd2638b36154 + } + }; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == g2); + + let s: u256 = 3; + let g3: G2Point = G2Point { + x0: u384 { + limb0: 0x866f09d516020ef82324afae, + limb1: 0xa0c75df1c04d6d7a50a030fc, + limb2: 0xdccb23ae691ae54329781315, + limb3: 0x122915c824a0857e2ee414a3 + }, + x1: u384 { + limb0: 0x937cc6d9d6a44aaa56ca66dc, + limb1: 0x5062650f8d251c96eb480673, + limb2: 0x7e0550ff2ac480905396eda5, + limb3: 0x9380275bbc8e5dcea7dc4dd + }, + y0: u384 { + limb0: 0x8b52fdf2455e44813ecfd892, + limb1: 0x326ac738fef5c721479dfd94, + limb2: 0xbc1a6f0136961d1e3b20b1a7, + limb3: 0xb21da7955969e61010c7a1a + }, + y1: u384 { + limb0: 0xb975b9edea56d53f23a0e849, + limb1: 0x714150a166bfbd6bcf6b3b58, + limb2: 0xa36cfe5f62a7e42e0bf1c1ed, + limb3: 0x8f239ba329b3967fe48d718 + } + }; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == g3); + + let s = 0xffffffffffffffffffffffffffffffff; + let g4: G2Point = G2Point { + x0: u384 { + limb0: 0xae40a8b5aee95e54aedee2e7, + limb1: 0x6e0699501c5035eed8fc5162, + limb2: 0xbee76829b76806d1b6617bf8, + limb3: 0x5026c3305c1267922077393 + }, + x1: u384 { + limb0: 0x10c08c4b0a70e02491c3c435, + limb1: 0x591ef738050b3ce067e2016f, + limb2: 0xdd6e0a179e2ce3c1399c5273, + limb3: 0xd5c9af9b97e94f90cb4aba3 + }, + y0: u384 { + limb0: 0x93be53660cebb92c90d4fa87, + limb1: 0xfbf63ca94e1d0ffd65801863, + limb2: 0xd24fd9a06d72f1dc57f15f0a, + limb3: 0x100dbfd4f271378e85171313 + }, + y1: u384 { + limb0: 0xb7296e587409163eecd3ef5d, + limb1: 0x8a065d6871fa185d15703e78, + limb2: 0x8a85fb95bb90eb5c7a0d81a9, + limb3: 0x157cf362e91a3c96640bd973 + } + }; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == g4); + + // + let s = 0x100000000000000000000000000000001; + let g5: G2Point = G2Point { + x0: u384 { + limb0: 0x2131be4b061714de5a11407d, + limb1: 0xd41318f9bcade1fee985310b, + limb2: 0xb2669e638a7b78b7ba5c6751, + limb3: 0xa5284fb2911d4e2f445e714 + }, + x1: u384 { + limb0: 0x712edcaf95ed642a8237e6fd, + limb1: 0xed6fccd7b64896ebb6ffb3d9, + limb2: 0xfcb88d23294a46657b8d2482, + limb3: 0x143ef485b660d37036fc18e2 + }, + y0: u384 { + limb0: 0xaa5b7ff57bdbf47e6ab49121, + limb1: 0xc14cded56b4a44e022320616, + limb2: 0xdd5105feb3fdc5b10edb5afa, + limb3: 0x175d2c78538490ce02fcead8 + }, + y1: u384 { + limb0: 0x23893f1bb0fdb0533584b05f, + limb1: 0x420d425d79dcd48b26d87814, + limb2: 0xc932fa90468e6b9dfd658cc9, + limb3: 0xe5fac70e9096e97adc6dd89 + } + }; + let r = ec_mul(g, s, curve_index).unwrap(); + assert!(r == g5); + } +} + diff --git a/src/src/groth16.cairo b/src/src/groth16.cairo index 96f78e3f..190deb33 100644 --- a/src/src/groth16.cairo +++ b/src/src/groth16.cairo @@ -40,8 +40,8 @@ use core::num::traits::{One}; use garaga::basic_field_ops::{neg_mod_p, compute_yInvXnegOverY_BN254}; -use garaga::ec_ops::{msm_g1, MSMHint, DerivePointFromXHint, G1PointTrait, G2PointTrait}; - +use garaga::ec_ops::{msm_g1, MSMHint, DerivePointFromXHint, G1PointTrait}; +use garaga::ec_ops_g2::G2PointTrait; use garaga::pairing_check::{MPCheckHintBN254, MPCheckHintBLS12_381}; use garaga::utils::{u384_assert_zero, usize_assert_eq}; use garaga::utils::hashing; diff --git a/src/src/lib.cairo b/src/src/lib.cairo index 6afee496..0e6f5d51 100644 --- a/src/src/lib.cairo +++ b/src/src/lib.cairo @@ -1,10 +1,12 @@ pub mod definitions; pub mod utils; pub mod ec_ops; +pub mod ec_ops_g2; pub mod pairing_check; pub mod circuits; pub mod groth16; pub mod basic_field_ops; +pub mod single_pairing_tower; mod tests; pub mod core; diff --git a/src/src/single_pairing_tower.cairo b/src/src/single_pairing_tower.cairo new file mode 100644 index 00000000..04bfbc52 --- /dev/null +++ b/src/src/single_pairing_tower.cairo @@ -0,0 +1,636 @@ +use garaga::definitions::{u384, U384One, U384Zero}; +use core::num::traits::{One, Zero}; +use garaga::definitions::{G1Point, G2Point, BNProcessedPair}; +use garaga::circuits::multi_pairing_check::{ + run_BN254_MP_CHECK_PREPARE_PAIRS_1P_circuit, run_BLS12_381_MP_CHECK_PREPARE_PAIRS_1P_circuit +}; + +use garaga::circuits::tower_circuits as tw; +use garaga::circuits::tower_circuits::{ + run_BN254_TOWER_MILLER_BIT0_1P_circuit, run_BN254_TOWER_MILLER_BIT1_1P_circuit, + run_BLS12_381_TOWER_MILLER_BIT0_1P_circuit, run_BLS12_381_TOWER_MILLER_BIT1_1P_circuit +}; +use garaga::basic_field_ops::compute_yInvXnegOverY_BLS12_381; +use garaga::ec_ops_g2::G2PointTrait; +// Fp12 tower struct. +#[derive(Drop, Copy, Debug, PartialEq)] +struct E12T { + c0b0a0: u384, + c0b0a1: u384, + c0b1a0: u384, + c0b1a1: u384, + c0b2a0: u384, + c0b2a1: u384, + c1b0a0: u384, + c1b0a1: u384, + c1b1a0: u384, + c1b1a1: u384, + c1b2a0: u384, + c1b2a1: u384, +} + +impl E12TOne of One { + fn one() -> E12T { + E12T { + c0b0a0: One::one(), + c0b0a1: Zero::zero(), + c0b1a0: Zero::zero(), + c0b1a1: Zero::zero(), + c0b2a0: Zero::zero(), + c0b2a1: Zero::zero(), + c1b0a0: Zero::zero(), + c1b0a1: Zero::zero(), + c1b1a0: Zero::zero(), + c1b1a1: Zero::zero(), + c1b2a0: Zero::zero(), + c1b2a1: Zero::zero(), + } + } + fn is_one(self: @E12T) -> bool { + *self == Self::one() + } + fn is_non_one(self: @E12T) -> bool { + !Self::is_one(self) + } +} + +pub fn miller_loop_bn254_tower(P: G1Point, Q: G2Point) -> (E12T,) { + let bits = bn_bits.span(); + + let (processed_pair): (BNProcessedPair,) = run_BN254_MP_CHECK_PREPARE_PAIRS_1P_circuit( + P, Q.y0, Q.y1 + ); + + let mut Mi: E12T = E12TOne::one(); + let mut Qi = Q; + + for bit in bits { + let (_Qi, _Mi) = match *bit { + 0 => { + run_BN254_TOWER_MILLER_BIT0_1P_circuit( + processed_pair.yInv, processed_pair.xNegOverY, Qi, Mi + ) + }, + 1 => { + run_BN254_TOWER_MILLER_BIT1_1P_circuit( + processed_pair.yInv, processed_pair.xNegOverY, Qi, Q, Mi + ) + }, + _ => { + run_BN254_TOWER_MILLER_BIT1_1P_circuit( + processed_pair.yInv, + processed_pair.xNegOverY, + Qi, + G2Point { + x0: Q.x0, x1: Q.x1, y0: processed_pair.QyNeg0, y1: processed_pair.QyNeg1 + }, + Mi + ) + }, + }; + Qi = _Qi; + Mi = _Mi; + }; + + tw::run_BN254_TOWER_MILLER_FINALIZE_BN_1P_circuit( + Q, processed_pair.yInv, processed_pair.xNegOverY, Qi, Mi + ) +} + +pub fn expt_bn254_tower(X: E12T) -> (E12T,) { + // Step 1 + let (t3) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(X); + // Step 2 + let (t5) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t3); + // Step 3 + let (result) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t5); + // Step 4 + let (t0) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(result); + // Step 5 + let (t2) = tw::run_BN254_E12T_MUL_circuit(X, t0); + // Step 6 + let (t0) = tw::run_BN254_E12T_MUL_circuit(t3, t2); + // Step 7 + let (t1) = tw::run_BN254_E12T_MUL_circuit(X, t0); + // Step 8 + let (t4) = tw::run_BN254_E12T_MUL_circuit(result, t2); + // Step 9 + let (t6) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t2); + // Step 10 + let (t1) = tw::run_BN254_E12T_MUL_circuit(t0, t1); + // Step 11 + let (t0) = tw::run_BN254_E12T_MUL_circuit(t3, t1); + // Step 17 + let mut t6 = t6; + for _ in 0..6_u8 { + let (_t6) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t6); + t6 = _t6; + }; + // Step 18 + let (t5) = tw::run_BN254_E12T_MUL_circuit(t5, t6); + // Step 19 + let (mut t5) = tw::run_BN254_E12T_MUL_circuit(t4, t5); + // Step 26 + for _ in 0..7_u8 { + let (_t5) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t5); + t5 = _t5; + }; + // Step 27 + let (mut t4) = tw::run_BN254_E12T_MUL_circuit(t4, t5); + // Step 35 + for _ in 0..8_u8 { + let (_t4) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t4); + t4 = _t4; + }; + // Step 36 + let (t4) = tw::run_BN254_E12T_MUL_circuit(t0, t4); + // Step 37 + let (mut t3) = tw::run_BN254_E12T_MUL_circuit(t3, t4); + // Step 43 + for _ in 0..6_u8 { + let (_t3) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t3); + t3 = _t3; + }; + // Step 44 + let (mut t2) = tw::run_BN254_E12T_MUL_circuit(t2, t3); + // Step 52 + for _ in 0..8_u8 { + let (_t2) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t2); + t2 = _t2; + }; + // Step 53 + let (mut t2) = tw::run_BN254_E12T_MUL_circuit(t0, t2); + + // Step 59 + for _ in 0..6_u8 { + let (_t2) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t2); + t2 = _t2; + }; + + // Step 60 + let (mut t2) = tw::run_BN254_E12T_MUL_circuit(t0, t2); + // Step 70 + for _ in 0..10_u8 { + let (_t2) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t2); + t2 = _t2; + }; + // Step 71 + let (mut t1) = tw::run_BN254_E12T_MUL_circuit(t1, t2); + // Step 77 + for _ in 0..6_u8 { + let (_t1) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + t1 = _t1; + }; + // Step 78 + let (t0) = tw::run_BN254_E12T_MUL_circuit(t0, t1); + // Step 79 + let (result) = tw::run_BN254_E12T_MUL_circuit(result, t0); + + return (result,); +} + +pub fn final_exp_bn254_tower(M: E12T) -> E12T { + let curve_id = 0; + let (t0) = fp12_conjugate(M, curve_id); + let (result) = tw::run_BN254_E12T_INVERSE_circuit(M); + let (t0) = tw::run_BN254_E12T_MUL_circuit(t0, result); + let (result) = tw::run_BN254_E12T_FROBENIUS_SQUARE_circuit(t0); + let (result) = tw::run_BN254_E12T_MUL_circuit(result, t0); + + // Hard part + let (t0) = expt_bn254_tower(result); + let (t0) = fp12_conjugate(t0, curve_id); + let (t0) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t0); + let (t1) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t0); + let (t1) = tw::run_BN254_E12T_MUL_circuit(t0, t1); + let (t2) = expt_bn254_tower(t1); + let (t2) = fp12_conjugate(t2, curve_id); + let (t3) = fp12_conjugate(t1, curve_id); + let (t1) = tw::run_BN254_E12T_MUL_circuit(t2, t3); + let (t3) = tw::run_BN254_E12T_CYCLOTOMIC_SQUARE_circuit(t2); + let (t4) = expt_bn254_tower(t3); + let (t4) = tw::run_BN254_E12T_MUL_circuit(t1, t4); + let (t3) = tw::run_BN254_E12T_MUL_circuit(t0, t4); + let (t0) = tw::run_BN254_E12T_MUL_circuit(t2, t4); + let (t0) = tw::run_BN254_E12T_MUL_circuit(result, t0); + let (t2) = tw::run_BN254_E12T_FROBENIUS_circuit(t3); + let (t0) = tw::run_BN254_E12T_MUL_circuit(t2, t0); + let (t2) = tw::run_BN254_E12T_FROBENIUS_SQUARE_circuit(t4); + let (t0) = tw::run_BN254_E12T_MUL_circuit(t2, t0); + let (t2) = fp12_conjugate(result, curve_id); + let (t2) = tw::run_BN254_E12T_MUL_circuit(t2, t3); + let (t2) = tw::run_BN254_E12T_FROBENIUS_CUBE_circuit(t2); + let (result) = tw::run_BN254_E12T_MUL_circuit(t2, t0); + + result +} + +#[inline] +pub fn fp12_conjugate(X: E12T, curve_id: usize) -> (E12T,) { + let (b0a0, b0a1, b1a0, b1a1, b2a0, b2a1) = tw::run_FP6_NEG_circuit( + X.c1b0a0, X.c1b0a1, X.c1b1a0, X.c1b1a1, X.c1b2a0, X.c1b2a1, curve_id + ); + ( + E12T { + c0b0a0: X.c0b0a0, + c0b0a1: X.c0b0a1, + c0b1a0: X.c0b1a0, + c0b1a1: X.c0b1a1, + c0b2a0: X.c0b2a0, + c0b2a1: X.c0b2a1, + c1b0a0: b0a0, + c1b0a1: b0a1, + c1b1a0: b1a0, + c1b1a1: b1a1, + c1b2a0: b2a0, + c1b2a1: b2a1, + }, + ) +} + +pub fn final_exp_bls12_381_tower(M: E12T) -> E12T { + let result = M; + let (t0) = fp12_conjugate(M, 1); + let (result) = tw::run_BLS12_381_E12T_INVERSE_circuit(result); + let (t0) = tw::run_BLS12_381_E12T_MUL_circuit(t0, result); + let (result) = tw::run_BLS12_381_E12T_FROBENIUS_SQUARE_circuit(t0); + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t0); + + let (t0) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(result); + let (t1) = expt_half_bls12_381_tower(t0); + let (t2) = fp12_conjugate(result, 1); + let (t1) = tw::run_BLS12_381_E12T_MUL_circuit(t1, t2); + let (t2) = expt_bls12_381_tower(t1); + let (t1) = fp12_conjugate(t1, 1); + let (t1) = tw::run_BLS12_381_E12T_MUL_circuit(t1, t2); + let (t2) = expt_bls12_381_tower(t1); + let (t1) = tw::run_BLS12_381_E12T_FROBENIUS_circuit(t1); + let (t1) = tw::run_BLS12_381_E12T_MUL_circuit(t1, t2); + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t0); + let (t0) = expt_bls12_381_tower(t1); + let (t2) = expt_bls12_381_tower(t0); + let (t0) = tw::run_BLS12_381_E12T_FROBENIUS_SQUARE_circuit(t1); + let (t1) = fp12_conjugate(t1, 1); + let (t1) = tw::run_BLS12_381_E12T_MUL_circuit(t1, t2); + let (t1) = tw::run_BLS12_381_E12T_MUL_circuit(t1, t0); + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t1); + result +} + +pub fn decompress_karabina_bls12_381(X: E12T) -> (E12T,) { + let (t0a0, t0a1, t1a0, t1a1) = match (X.c1b2a0.is_zero() && X.c1b2a1.is_zero()) { + true => { + let (t0a0, t0a1) = tw::run_BLS12_381_E12T_DECOMP_KARABINA_I_Z_circuit( + X.c0b1a0, X.c0b1a1, X.c1b2a0, X.c1b2a1 + ); + (t0a0, t0a1, X.c0b2a0, X.c0b2a1) + }, + false => { + tw::run_BLS12_381_E12T_DECOMP_KARABINA_I_NZ_circuit( + X.c0b1a0, X.c0b1a1, X.c0b2a0, X.c0b2a1, X.c1b0a0, X.c1b0a1, X.c1b2a0, X.c1b2a1 + ) + } + }; + + if t1a0.is_zero() && t1a1.is_zero() { + return (One::one(),); + } + + let (zc0b0a0, zc0b0a1, zc1b1a0, zc1b1a1) = tw::run_BLS12_381_E12T_DECOMP_KARABINA_II_circuit( + t0a0, + t0a1, + t1a0, + t1a1, + X.c0b1a0, + X.c0b1a1, + X.c0b2a0, + X.c0b2a1, + X.c1b0a0, + X.c1b0a1, + X.c1b2a0, + X.c1b2a1 + ); + + ( + E12T { + c0b0a0: zc0b0a0, + c0b0a1: zc0b0a1, + c0b1a0: X.c0b1a0, + c0b1a1: X.c0b1a1, + c0b2a0: X.c0b2a0, + c0b2a1: X.c0b2a1, + c1b0a0: X.c1b0a0, + c1b0a1: X.c1b0a1, + c1b1a0: zc1b1a0, + c1b1a1: zc1b1a1, + c1b2a0: X.c1b2a0, + c1b2a1: X.c1b2a1, + }, + ) +} +pub fn expt_half_bls12_381_tower(M: E12T) -> (E12T,) { + let ( + mut xc0b1a0, + mut xc0b1a1, + mut xc0b2a0, + mut xc0b2a1, + mut xc1b0a0, + mut xc1b0a1, + mut xc1b2a0, + mut xc1b2a1 + ) = + ( + M.c0b1a0, M.c0b1a1, M.c0b2a0, M.c0b2a1, M.c1b0a0, M.c1b0a1, M.c1b2a0, M.c1b2a1 + ); + for _ in 0 + ..15_u32 { + let (_xc0b1a0, _xc0b1a1, _xc0b2a0, _xc0b2a1, _xc1b0a0, _xc1b0a1, _xc1b2a0, _xc1b2a1) = + tw::run_BLS12_381_E12T_CYCLO_SQUARE_COMPRESSED_circuit( + xc0b1a0, xc0b1a1, xc0b2a0, xc0b2a1, xc1b0a0, xc1b0a1, xc1b2a0, xc1b2a1 + ); + xc0b1a0 = _xc0b1a0; + xc0b1a1 = _xc0b1a1; + xc0b2a0 = _xc0b2a0; + xc0b2a1 = _xc0b2a1; + xc1b0a0 = _xc1b0a0; + xc1b0a1 = _xc1b0a1; + xc1b2a0 = _xc1b2a0; + xc1b2a1 = _xc1b2a1; + }; + + let t0c0b1a0 = xc0b1a0; + let t0c0b1a1 = xc0b1a1; + let t0c0b2a0 = xc0b2a0; + let t0c0b2a1 = xc0b2a1; + let t0c1b0a0 = xc1b0a0; + let t0c1b0a1 = xc1b0a1; + let t0c1b2a0 = xc1b2a0; + let t0c1b2a1 = xc1b2a1; + + let ( + mut xc0b1a0, + mut xc0b1a1, + mut xc0b2a0, + mut xc0b2a1, + mut xc1b0a0, + mut xc1b0a1, + mut xc1b2a0, + mut xc1b2a1 + ) = + ( + xc0b1a0, xc0b1a1, xc0b2a0, xc0b2a1, xc1b0a0, xc1b0a1, xc1b2a0, xc1b2a1 + ); + for _ in 0 + ..32_u32 { + let (_xc0b1a0, _xc0b1a1, _xc0b2a0, _xc0b2a1, _xc1b0a0, _xc1b0a1, _xc1b2a0, _xc1b2a1) = + tw::run_BLS12_381_E12T_CYCLO_SQUARE_COMPRESSED_circuit( + xc0b1a0, xc0b1a1, xc0b2a0, xc0b2a1, xc1b0a0, xc1b0a1, xc1b2a0, xc1b2a1 + ); + xc0b1a0 = _xc0b1a0; + xc0b1a1 = _xc0b1a1; + xc0b2a0 = _xc0b2a0; + xc0b2a1 = _xc0b2a1; + xc1b0a0 = _xc1b0a0; + xc1b0a1 = _xc1b0a1; + xc1b2a0 = _xc1b2a0; + xc1b2a1 = _xc1b2a1; + }; + + let (t0) = decompress_karabina_bls12_381( + E12T { + c0b0a0: M.c0b0a0, + c0b0a1: M.c0b0a1, + c0b1a0: t0c0b1a0, + c0b1a1: t0c0b1a1, + c0b2a0: t0c0b2a0, + c0b2a1: t0c0b2a1, + c1b0a0: t0c1b0a0, + c1b0a1: t0c1b0a1, + c1b1a0: M.c1b1a0, + c1b1a1: M.c1b1a1, + c1b2a0: t0c1b2a0, + c1b2a1: t0c1b2a1, + } + ); + + let (mut t1) = decompress_karabina_bls12_381( + E12T { + c0b0a0: M.c0b0a0, + c0b0a1: M.c0b0a1, + c0b1a0: xc0b1a0, + c0b1a1: xc0b1a1, + c0b2a0: xc0b2a0, + c0b2a1: xc0b2a1, + c1b0a0: xc1b0a0, + c1b0a1: xc1b0a1, + c1b1a0: M.c1b1a0, + c1b1a1: M.c1b1a1, + c1b2a0: xc1b2a0, + c1b2a1: xc1b2a1, + } + ); + + let (mut result) = tw::run_BLS12_381_E12T_MUL_circuit(t0, t1); + + for _ in 0 + ..9_u32 { + let (_t1) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + t1 = _t1; + }; + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t1); + for _ in 0 + ..3_u32 { + let (_t1) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + t1 = _t1; + }; + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t1); + // 2 sq + let (t1) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + let (t1) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t1); + let (t1) = tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t1); + let (result) = tw::run_BLS12_381_E12T_MUL_circuit(result, t1); + let (result) = fp12_conjugate(result, 1); + (result,) +} + +pub fn expt_bls12_381_tower(M: E12T) -> (E12T,) { + let (t0) = expt_half_bls12_381_tower(M); + return tw::run_BLS12_381_E12T_CYCLOTOMIC_SQUARE_circuit(t0); +} + +pub fn miller_loop_bls12_381_tower(P: G1Point, Q: G2Point) -> (E12T,) { + let bits = bls_bits.span(); + + let (yInv, xNegOverY) = compute_yInvXnegOverY_BLS12_381(P.x, P.y); + + let (TripleQ, c0b0a0, c0b0a1, c0b1a0, c0b1a1, c0b2a0, c0b2a1, c1b1a0, c1b1a1, c1b2a0, c1b2a1) = + tw::run_BLS12_381_TOWER_MILLER_INIT_BIT_1P_circuit( + yInv, xNegOverY, Q + ); + + let mut Mi: E12T = E12T { + c0b0a0: c0b0a0, + c0b0a1: c0b0a1, + c0b1a0: c0b1a0, + c0b1a1: c0b1a1, + c0b2a0: c0b2a0, + c0b2a1: c0b2a1, + c1b0a0: Zero::zero(), + c1b0a1: Zero::zero(), + c1b1a0: c1b1a0, + c1b1a1: c1b1a1, + c1b2a0: c1b2a0, + c1b2a1: c1b2a1, + }; + + let mut Qi = TripleQ; + for bit in bits { + let (_Qi, _Mi) = match *bit { + 0 => { tw::run_BLS12_381_TOWER_MILLER_BIT0_1P_circuit(yInv, xNegOverY, Qi, Mi) }, + _ => { tw::run_BLS12_381_TOWER_MILLER_BIT1_1P_circuit(yInv, xNegOverY, Qi, Q, Mi) }, + }; + Qi = _Qi; + Mi = _Mi; + }; + + return fp12_conjugate(Mi, 1); +} + + +const bn_bits: [ + usize + ; 65] = [ + 0, + 2, + 0, + 1, + 0, + 0, + 0, + 2, + 0, + 2, + 0, + 0, + 0, + 2, + 0, + 0, + 1, + 1, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 2, + 0, + 1, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 2, + 0, + 1, + 0, + 0, + 0, + 2, + 0, + 2, + 0, + 0, + 1, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 2, + 0, + 2, + 2, + 0, + 0, + 0 +]; + +const bls_bits: [ + usize + ; 62] = [ + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 +]; diff --git a/src/src/tests.cairo b/src/src/tests.cairo index 27b4f20b..d605eaa3 100644 --- a/src/src/tests.cairo +++ b/src/src/tests.cairo @@ -1,2 +1,3 @@ mod pairing_tests; mod msm_tests; +mod tower_pairing_tests; diff --git a/src/src/tests/tower_pairing_tests.cairo b/src/src/tests/tower_pairing_tests.cairo new file mode 100644 index 00000000..2334d170 --- /dev/null +++ b/src/src/tests/tower_pairing_tests.cairo @@ -0,0 +1,1297 @@ +#[cfg(test)] +mod tower_pairing_tests { + use garaga::single_pairing_tower::{ + E12TOne, u384, G1Point, G2Point, E12T, miller_loop_bls12_381_tower, miller_loop_bn254_tower, + final_exp_bls12_381_tower, final_exp_bn254_tower, expt_half_bls12_381_tower + }; + use garaga::ec_ops::{G1PointImpl}; + use garaga::ec_ops_g2::{G2PointImpl}; + use garaga::circuits::tower_circuits::{ + run_BN254_E12T_MUL_circuit, run_BLS12_381_E12T_MUL_circuit + }; + + #[test] + fn test_tower_pairing_BN254_1P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + y: u384 { limb0: 0x2, limb1: 0x0, limb2: 0x0, limb3: 0x0 } + }; + + p0.assert_on_curve(0); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0xf75edadd46debd5cd992f6ed, + limb1: 0x426a00665e5c4479674322d4, + limb2: 0x1800deef121f1e76, + limb3: 0x0 + }, + x1: u384 { + limb0: 0x35a9e71297e485b7aef312c2, + limb1: 0x7260bfb731fb5d25f1aa4933, + limb2: 0x198e9393920d483a, + limb3: 0x0 + }, + y0: u384 { + limb0: 0xc43d37b4ce6cc0166fa7daa, + limb1: 0x4aab71808dcb408fe3d1e769, + limb2: 0x12c85ea5db8c6deb, + limb3: 0x0 + }, + y1: u384 { + limb0: 0x70b38ef355acdadcd122975b, + limb1: 0xec9e99ad690c3395bc4b3133, + limb2: 0x90689d0585ff075, + limb3: 0x0 + } + }; + + q0.assert_on_curve(0); + let (tmp0) = miller_loop_bn254_tower(p0, q0); + let (res) = run_BN254_E12T_MUL_circuit(tmp0, res); + let final = final_exp_bn254_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { + limb0: 0x898578b55e1f63739d870e95, + limb1: 0xda01bde280a3ed6f87e5feb, + limb2: 0x262b253feda94cfe, + limb3: 0x0 + }, + c0b0a1: u384 { + limb0: 0x918ed66b49d34b48efb8a4a, + limb1: 0xa1b1f823879abbd397c4dea, + limb2: 0x2e02d2cc795a200, + limb3: 0x0 + }, + c0b1a0: u384 { + limb0: 0x87ecb1fc4e135402fdbd1de0, + limb1: 0xa5b1ad44b31977935fd29573, + limb2: 0x13a9f2d6e29b128d, + limb3: 0x0 + }, + c0b1a1: u384 { + limb0: 0x699ce630b130b08a6ea1162b, + limb1: 0x4b31984a74e68659c4b420bd, + limb2: 0x40ba9fa500f1a5c, + limb3: 0x0 + }, + c0b2a0: u384 { + limb0: 0x211ce30bf5e3eeaef89eafdb, + limb1: 0xbe359d7f9873f052478f590b, + limb2: 0xafc2f3fd870678f, + limb3: 0x0 + }, + c0b2a1: u384 { + limb0: 0xcc5a8243f9cddbd2d98dd1f0, + limb1: 0xbdc662d929e645cadda9a712, + limb2: 0x1c54a530398c9064, + limb3: 0x0 + }, + c1b0a0: u384 { + limb0: 0xfd4b7aef5c0d58c5dc2429fe, + limb1: 0x23794a0d856f92591ba990ec, + limb2: 0x95c0fbf5d5a1ac0, + limb3: 0x0 + }, + c1b0a1: u384 { + limb0: 0x590cb4a60f8215d4b99f2b4a, + limb1: 0xa31dc10f7b4053c9e9ad9ebb, + limb2: 0x14d3d6ca72d8a950, + limb3: 0x0 + }, + c1b1a0: u384 { + limb0: 0x43c585fdfaf545838ca7429, + limb1: 0x89dc206b4b91c85759dc1a23, + limb2: 0x1dc0e7bbc3d70e66, + limb3: 0x0 + }, + c1b1a1: u384 { + limb0: 0xac16cc1b7ab2cd3ed5e22b97, + limb1: 0x98a855ffc837d2a75ab90d61, + limb2: 0xb53320e5a6488cb, + limb3: 0x0 + }, + c1b2a0: u384 { + limb0: 0xc42a9c0f9bd7fddaf5ebd723, + limb1: 0x6c91476ef36cd1d318ce07ba, + limb2: 0x13a8afd3085dae4c, + limb3: 0x0 + }, + c1b2a1: u384 { + limb0: 0x43940c383e5314859e762c97, + limb1: 0xb601f3730a3afa965ceee1b3, + limb2: 0xf97b5221474526, + limb3: 0x0 + } + } + ); + } + + + #[test] + fn test_tower_pairing_BN254_2P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { + limb0: 0xcdb6d03cb7b9a5409b7efcd8, + limb1: 0xd1df87eab84852372b905c9c, + limb2: 0x1d0634f3f21e7890, + limb3: 0x0 + }, + y: u384 { + limb0: 0xaa1d4f4d3021032564460978, + limb1: 0xeb3f1d6ba3b10e2b53dc193b, + limb2: 0x24c53532773dce26, + limb3: 0x0 + } + }; + + p0.assert_on_curve(0); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0xf75edadd46debd5cd992f6ed, + limb1: 0x426a00665e5c4479674322d4, + limb2: 0x1800deef121f1e76, + limb3: 0x0 + }, + x1: u384 { + limb0: 0x35a9e71297e485b7aef312c2, + limb1: 0x7260bfb731fb5d25f1aa4933, + limb2: 0x198e9393920d483a, + limb3: 0x0 + }, + y0: u384 { + limb0: 0xc43d37b4ce6cc0166fa7daa, + limb1: 0x4aab71808dcb408fe3d1e769, + limb2: 0x12c85ea5db8c6deb, + limb3: 0x0 + }, + y1: u384 { + limb0: 0x70b38ef355acdadcd122975b, + limb1: 0xec9e99ad690c3395bc4b3133, + limb2: 0x90689d0585ff075, + limb3: 0x0 + } + }; + + q0.assert_on_curve(0); + let (tmp0) = miller_loop_bn254_tower(p0, q0); + let (res) = run_BN254_E12T_MUL_circuit(tmp0, res); + let p1: G1Point = G1Point { + x: u384 { + limb0: 0x536c985db33c69f7c242e07a, + limb1: 0xfc531bccffafcf1e59d91fb9, + limb2: 0x2585e4f8a31664cb, + limb3: 0x0 + }, + y: u384 { + limb0: 0x57fa42444057cf0c1d62ae3c, + limb1: 0x4f48d341183118d68ea41313, + limb2: 0x1d2d2799db056ed1, + limb3: 0x0 + } + }; + + p1.assert_on_curve(0); + let q1: G2Point = G2Point { + x0: u384 { + limb0: 0x335eb0538f718d8e6651eeb1, + limb1: 0x635e573808d9d5c7178bdce7, + limb2: 0x1314aaf1c372e6d7, + limb3: 0x0 + }, + x1: u384 { + limb0: 0x5289f29ccc5acf5e81526673, + limb1: 0x2d4aba9e1448a8cc1048d01a, + limb2: 0x14c25d3aec745e5a, + limb3: 0x0 + }, + y0: u384 { + limb0: 0x10d1d0efd5869ecd23aab8e9, + limb1: 0xba7d1de6d86501d49b6a8dab, + limb2: 0x397391b7b25e2f, + limb3: 0x0 + }, + y1: u384 { + limb0: 0x385a553ea12434f4eda6db36, + limb1: 0xb058c1ff7e4c5c7ec7e5859b, + limb2: 0x1863ac65eca09e89, + limb3: 0x0 + } + }; + + q1.assert_on_curve(0); + let (tmp1) = miller_loop_bn254_tower(p1, q1); + let (res) = run_BN254_E12T_MUL_circuit(tmp1, res); + let final = final_exp_bn254_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 } + } + ); + } + + + #[test] + fn test_tower_pairing_BN254_3P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { + limb0: 0x5c724369afbc772d02aed58e, + limb1: 0x2cd3bc838c66439a3d6160b, + limb2: 0x72f26b55fb56be1, + limb3: 0x0 + }, + y: u384 { + limb0: 0x772ca79c580e121ca148fe75, + limb1: 0xce2f55e418ca01b3d6d1014b, + limb2: 0x2884b1dc4e84e30f, + limb3: 0x0 + } + }; + + p0.assert_on_curve(0); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0xa30b422f34656d6c94e40be, + limb1: 0x83069b5050fd7194c7e35d0c, + limb2: 0xf0e8184945e8d34, + limb3: 0x0 + }, + x1: u384 { + limb0: 0xde9079ee8fa5e15901dfef27, + limb1: 0xdb602cf367841e5047ffab14, + limb2: 0x1752c7b6b35af45, + limb3: 0x0 + }, + y0: u384 { + limb0: 0x4dafbd7f615fd2aa9f5a0acc, + limb1: 0x35c8bbffe201ffd56deb5dea, + limb2: 0xa822a5ba029a283, + limb3: 0x0 + }, + y1: u384 { + limb0: 0xec6d9e4fafec17b8404c0341, + limb1: 0x17fe961ad4b8ee3bf2ade626, + limb2: 0x1228147f83e3ea5, + limb3: 0x0 + } + }; + + q0.assert_on_curve(0); + let (tmp0) = miller_loop_bn254_tower(p0, q0); + let (res) = run_BN254_E12T_MUL_circuit(tmp0, res); + let p1: G1Point = G1Point { + x: u384 { + limb0: 0x5c724369afbc772d02aed58e, + limb1: 0x2cd3bc838c66439a3d6160b, + limb2: 0x72f26b55fb56be1, + limb3: 0x0 + }, + y: u384 { + limb0: 0x772ca79c580e121ca148fe75, + limb1: 0xce2f55e418ca01b3d6d1014b, + limb2: 0x2884b1dc4e84e30f, + limb3: 0x0 + } + }; + + p1.assert_on_curve(0); + let q1: G2Point = G2Point { + x0: u384 { + limb0: 0xa30b422f34656d6c94e40be, + limb1: 0x83069b5050fd7194c7e35d0c, + limb2: 0xf0e8184945e8d34, + limb3: 0x0 + }, + x1: u384 { + limb0: 0xde9079ee8fa5e15901dfef27, + limb1: 0xdb602cf367841e5047ffab14, + limb2: 0x1752c7b6b35af45, + limb3: 0x0 + }, + y0: u384 { + limb0: 0x4dafbd7f615fd2aa9f5a0acc, + limb1: 0x35c8bbffe201ffd56deb5dea, + limb2: 0xa822a5ba029a283, + limb3: 0x0 + }, + y1: u384 { + limb0: 0xec6d9e4fafec17b8404c0341, + limb1: 0x17fe961ad4b8ee3bf2ade626, + limb2: 0x1228147f83e3ea5, + limb3: 0x0 + } + }; + + q1.assert_on_curve(0); + let (tmp1) = miller_loop_bn254_tower(p1, q1); + let (res) = run_BN254_E12T_MUL_circuit(tmp1, res); + let p2: G1Point = G1Point { + x: u384 { + limb0: 0x8dcb6db105ead17484cff544, + limb1: 0x95151f1c65bf4c2e698b5634, + limb2: 0xc83f07e39979c6a, + limb3: 0x0 + }, + y: u384 { + limb0: 0x38cf77eafd4a4fdd9e46575, + limb1: 0x3cf1e428854a9a0e559814bc, + limb2: 0x15571140da88fd37, + limb3: 0x0 + } + }; + + p2.assert_on_curve(0); + let q2: G2Point = G2Point { + x0: u384 { + limb0: 0xa30b422f34656d6c94e40be, + limb1: 0x83069b5050fd7194c7e35d0c, + limb2: 0xf0e8184945e8d34, + limb3: 0x0 + }, + x1: u384 { + limb0: 0xde9079ee8fa5e15901dfef27, + limb1: 0xdb602cf367841e5047ffab14, + limb2: 0x1752c7b6b35af45, + limb3: 0x0 + }, + y0: u384 { + limb0: 0x4dafbd7f615fd2aa9f5a0acc, + limb1: 0x35c8bbffe201ffd56deb5dea, + limb2: 0xa822a5ba029a283, + limb3: 0x0 + }, + y1: u384 { + limb0: 0xec6d9e4fafec17b8404c0341, + limb1: 0x17fe961ad4b8ee3bf2ade626, + limb2: 0x1228147f83e3ea5, + limb3: 0x0 + } + }; + + q2.assert_on_curve(0); + let (tmp2) = miller_loop_bn254_tower(p2, q2); + let (res) = run_BN254_E12T_MUL_circuit(tmp2, res); + let final = final_exp_bn254_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 } + } + ); + } + + + #[test] + fn test_tower_pairing_BLS12_381_1P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { + limb0: 0xf97a1aeffb3af00adb22c6bb, + limb1: 0xa14e3a3f171bac586c55e83f, + limb2: 0x4fa9ac0fc3688c4f9774b905, + limb3: 0x17f1d3a73197d7942695638c + }, + y: u384 { + limb0: 0xa2888ae40caa232946c5e7e1, + limb1: 0xdb18cb2c04b3edd03cc744, + limb2: 0x741d8ae4fcf5e095d5d00af6, + limb3: 0x8b3f481e3aaa0f1a09e30ed + } + }; + + p0.assert_on_curve(1); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0xa805bbefd48056c8c121bdb8, + limb1: 0xb4510b647ae3d1770bac0326, + limb2: 0x2dc51051c6e47ad4fa403b02, + limb3: 0x24aa2b2f08f0a9126080527 + }, + x1: u384 { + limb0: 0x13945d57e5ac7d055d042b7e, + limb1: 0xb5da61bbdc7f5049334cf112, + limb2: 0x88274f65596bd0d09920b61a, + limb3: 0x13e02b6052719f607dacd3a0 + }, + y0: u384 { + limb0: 0x3baca289e193548608b82801, + limb1: 0x6d429a695160d12c923ac9cc, + limb2: 0xda2e351aadfd9baa8cbdd3a7, + limb3: 0xce5d527727d6e118cc9cdc6 + }, + y1: u384 { + limb0: 0x5cec1da1aaa9075ff05f79be, + limb1: 0x267492ab572e99ab3f370d27, + limb2: 0x2bc28b99cb3e287e85a763af, + limb3: 0x606c4a02ea734cc32acd2b0 + } + }; + + q0.assert_on_curve(1); + let (tmp0) = miller_loop_bls12_381_tower(p0, q0); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp0, res); + let final = final_exp_bls12_381_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { + limb0: 0x839c508a84305aaca1789b6, + limb1: 0x3dd8e90ce98db3e7b6d194f6, + limb2: 0x68d0d727272d441befa15c50, + limb3: 0x1250ebd871fc0a92a7b2d831 + }, + c0b0a1: u384 { + limb0: 0x50439f1d59882a98eaa0170f, + limb1: 0xaf5af689452eafabf1a8943e, + limb2: 0xa532348868a84045483c92b7, + limb3: 0x89a1c5b46e5110b86750ec6 + }, + c0b1a0: u384 { + limb0: 0x9396b38c881c4c849ec23e87, + limb1: 0x16da0e22a5031b54ddff5730, + limb2: 0x689ce34c0378a68e72a6b3b2, + limb3: 0x1368bb445c7c2d209703f239 + }, + c0b1a1: u384 { + limb0: 0x579973b1315021ec3c19934f, + limb1: 0x7c90d8bd66065b1fffe51d7a, + limb2: 0x5a50512937e0794e1e65a761, + limb3: 0x193502b86edb8857c273fa07 + }, + c0b2a0: u384 { + limb0: 0xbbaad8431dad1c1fb597aaa5, + limb1: 0x185203fcca589ac719c34dff, + limb2: 0x4dc4007cfbf2f8da752f7c74, + limb3: 0x1b2f522473d171391125ba8 + }, + c0b2a1: u384 { + limb0: 0xa35c8ca78beae9624045b4b6, + limb1: 0x8061e55cceba478b23f7daca, + limb2: 0x7a45b84546da634b8f6be14a, + limb3: 0x18107154f25a764bd3c7993 + }, + c1b0a0: u384 { + limb0: 0x86a8703e0f948226e47ee89d, + limb1: 0xdea54d43b2b73f2cbb12d583, + limb2: 0xc3d5a04dc88784fbb3d0b2db, + limb3: 0x19f26337d205fb469cd6bd15 + }, + c1b0a1: u384 { + limb0: 0xff02f0b8102ae1c2d5d5ab1a, + limb1: 0xa7d2809d61bfe02e1bfd1b68, + limb2: 0xa771b6ffd5857baaf222eb95, + limb3: 0x6fba23eb7c5af0d9f80940c + }, + c1b1a0: u384 { + limb0: 0x1e32fac91b93b47333e2ba57, + limb1: 0x7d0d15ff7b984e8978ef4888, + limb2: 0x3b0b0ec5c81a93b330ee1a67, + limb3: 0x11b8b424cd48bf38fcef6808 + }, + c1b1a1: u384 { + limb0: 0xa09ffdd9be2291a0c25a99a2, + limb1: 0x20c806ad360829107ba810c5, + limb2: 0x6ce5771cc6a0e9786ab59733, + limb3: 0x3350f55a7aefcd3c31b4fcb + }, + c1b2a0: u384 { + limb0: 0x66245cb9108f0242d0fe3ef, + limb1: 0x1c7cdba7b3872629a4fafc05, + limb2: 0x728ffd21a189e87935a95405, + limb3: 0x4c581234d086a9902249b64 + }, + c1b2a1: u384 { + limb0: 0xafe47e1efde449383b676631, + limb1: 0xdeff686bfd6df543d48eaa24, + limb2: 0xd01a7ec73baca4d72ca93544, + limb3: 0xf41e58663bf08cf068672cb + } + } + ); + } + + + #[test] + fn test_tower_pairing_BLS12_381_2P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { + limb0: 0xfe174bb39be8658ef83c8c2d, + limb1: 0xdb24ddec0e0c3b63d82efa81, + limb2: 0xe360a80121d5ef96fd687003, + limb3: 0x59d2a79bda5f8a941d4db9 + }, + y: u384 { + limb0: 0x7f68344f543e52fe891285a9, + limb1: 0x6f6992be16bc35f88c471acf, + limb2: 0xcebb5ee96e40a033f5d3b798, + limb3: 0x2df47e8cdf189985d5085bd + } + }; + + p0.assert_on_curve(1); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0xa805bbefd48056c8c121bdb8, + limb1: 0xb4510b647ae3d1770bac0326, + limb2: 0x2dc51051c6e47ad4fa403b02, + limb3: 0x24aa2b2f08f0a9126080527 + }, + x1: u384 { + limb0: 0x13945d57e5ac7d055d042b7e, + limb1: 0xb5da61bbdc7f5049334cf112, + limb2: 0x88274f65596bd0d09920b61a, + limb3: 0x13e02b6052719f607dacd3a0 + }, + y0: u384 { + limb0: 0x3baca289e193548608b82801, + limb1: 0x6d429a695160d12c923ac9cc, + limb2: 0xda2e351aadfd9baa8cbdd3a7, + limb3: 0xce5d527727d6e118cc9cdc6 + }, + y1: u384 { + limb0: 0x5cec1da1aaa9075ff05f79be, + limb1: 0x267492ab572e99ab3f370d27, + limb2: 0x2bc28b99cb3e287e85a763af, + limb3: 0x606c4a02ea734cc32acd2b0 + } + }; + + q0.assert_on_curve(1); + let (tmp0) = miller_loop_bls12_381_tower(p0, q0); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp0, res); + let p1: G1Point = G1Point { + x: u384 { + limb0: 0xde4f62a6588c9401ffefbd3, + limb1: 0x9bb5f797ac6d3395b71420b5, + limb2: 0xdc39e973aaf31de52219df08, + limb3: 0x105dcc4dce3960447d21d3c1 + }, + y: u384 { + limb0: 0xaefd0d854043fd325dd3c34f, + limb1: 0x9b63c98d9a7845c52e1e2b0f, + limb2: 0x9db0be660d847ccc58358f3f, + limb3: 0x17cb6c41f0c4e1a7394ab62a + } + }; + + p1.assert_on_curve(1); + let q1: G2Point = G2Point { + x0: u384 { + limb0: 0x3b3d3c305a70960906e6cb09, + limb1: 0x40e5bf3ff02d81e98b75703a, + limb2: 0x665a5fc010510bd690ddd7b5, + limb3: 0x82dc9154807866eb0f36ccb + }, + x1: u384 { + limb0: 0xe6709deb0dcf81d4285e5e60, + limb1: 0xb4dcf956002c4efb974ffcee, + limb2: 0x4a6ceebe6375a83dd242851b, + limb3: 0xdd18d077ad5bd58dabb18d8 + }, + y0: u384 { + limb0: 0x61535fe1a90bae7e6692f9b0, + limb1: 0xc91aa58105d3a281b2e84ddb, + limb2: 0x197d3446652372ce5ef50e93, + limb3: 0x4a468eb9e206b9833d8e8e2 + }, + y1: u384 { + limb0: 0x27115c334e82ed4be8da6c10, + limb1: 0x194fa3bf769a2e5a52535277, + limb2: 0x8be8992de81f47ae3341c590, + limb3: 0x198fd0ab6249082bf7007d7e + } + }; + + q1.assert_on_curve(1); + let (tmp1) = miller_loop_bls12_381_tower(p1, q1); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp1, res); + let final = final_exp_bls12_381_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 } + } + ); + } + + + #[test] + fn test_tower_pairing_BLS12_381_3P() { + let mut res: E12T = E12TOne::one(); + + let p0: G1Point = G1Point { + x: u384 { + limb0: 0xe4f817e54aede0613c17035c, + limb1: 0xdff1f15010392a6da1f95a6, + limb2: 0xbed78d3d341e911d49f15454, + limb3: 0x18154782ce0913b21588066d + }, + y: u384 { + limb0: 0x3d77d61326ef5a9a5a681757, + limb1: 0xd3070afd4f0e121de7fcee60, + limb2: 0xdf9ef4088763fe611fb85858, + limb3: 0x11a612bdd0bc09562856a70 + } + }; + + p0.assert_on_curve(1); + let q0: G2Point = G2Point { + x0: u384 { + limb0: 0x30d2fddc2fa171cdd4d31a55, + limb1: 0x92fab4f255a20d09700542e5, + limb2: 0x4d92a8c02d22b8cea4ff21ab, + limb3: 0x120a838699abaae7ed948194 + }, + x1: u384 { + limb0: 0x51cd5fdc71cf4557ef606935, + limb1: 0x92e1b13e2c93fc9957b17841, + limb2: 0x6143a906b63b7f3476ad6819, + limb3: 0x158186f6f2dd04cfa4e78547 + }, + y0: u384 { + limb0: 0x9f1c7dcdbe4574f05d0c093b, + limb1: 0xcde395f3ee4e353cf25a2e21, + limb2: 0x6a44c4a6d642c3dd98128703, + limb3: 0x2bd32fdfe26d866771e2180 + }, + y1: u384 { + limb0: 0x7060005397ea11f7e9a26050, + limb1: 0xeb8540654b533da9b594fc27, + limb2: 0xfc83cf9d283b7231df1db3f9, + limb3: 0x7ff9623d918ca12e0ff6cce + } + }; + + q0.assert_on_curve(1); + let (tmp0) = miller_loop_bls12_381_tower(p0, q0); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp0, res); + let p1: G1Point = G1Point { + x: u384 { + limb0: 0xe4f817e54aede0613c17035c, + limb1: 0xdff1f15010392a6da1f95a6, + limb2: 0xbed78d3d341e911d49f15454, + limb3: 0x18154782ce0913b21588066d + }, + y: u384 { + limb0: 0x3d77d61326ef5a9a5a681757, + limb1: 0xd3070afd4f0e121de7fcee60, + limb2: 0xdf9ef4088763fe611fb85858, + limb3: 0x11a612bdd0bc09562856a70 + } + }; + + p1.assert_on_curve(1); + let q1: G2Point = G2Point { + x0: u384 { + limb0: 0x30d2fddc2fa171cdd4d31a55, + limb1: 0x92fab4f255a20d09700542e5, + limb2: 0x4d92a8c02d22b8cea4ff21ab, + limb3: 0x120a838699abaae7ed948194 + }, + x1: u384 { + limb0: 0x51cd5fdc71cf4557ef606935, + limb1: 0x92e1b13e2c93fc9957b17841, + limb2: 0x6143a906b63b7f3476ad6819, + limb3: 0x158186f6f2dd04cfa4e78547 + }, + y0: u384 { + limb0: 0x9f1c7dcdbe4574f05d0c093b, + limb1: 0xcde395f3ee4e353cf25a2e21, + limb2: 0x6a44c4a6d642c3dd98128703, + limb3: 0x2bd32fdfe26d866771e2180 + }, + y1: u384 { + limb0: 0x7060005397ea11f7e9a26050, + limb1: 0xeb8540654b533da9b594fc27, + limb2: 0xfc83cf9d283b7231df1db3f9, + limb3: 0x7ff9623d918ca12e0ff6cce + } + }; + + q1.assert_on_curve(1); + let (tmp1) = miller_loop_bls12_381_tower(p1, q1); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp1, res); + let p2: G1Point = G1Point { + x: u384 { + limb0: 0x6b2dbb412523879f8e3a96a0, + limb1: 0x6daa411c3d8c33de611bc2fe, + limb2: 0x38ff9a4921f13749974e4731, + limb3: 0x2b2fcedd1d05f99449b4884 + }, + y: u384 { + limb0: 0x845744e5af99690d2a360ec2, + limb1: 0x56b0c0147f0ee90a5c1b6e41, + limb2: 0xdee769045aef4994aab4b4fc, + limb3: 0x32b985c03cd5519d41d0cbb + } + }; + + p2.assert_on_curve(1); + let q2: G2Point = G2Point { + x0: u384 { + limb0: 0x30d2fddc2fa171cdd4d31a55, + limb1: 0x92fab4f255a20d09700542e5, + limb2: 0x4d92a8c02d22b8cea4ff21ab, + limb3: 0x120a838699abaae7ed948194 + }, + x1: u384 { + limb0: 0x51cd5fdc71cf4557ef606935, + limb1: 0x92e1b13e2c93fc9957b17841, + limb2: 0x6143a906b63b7f3476ad6819, + limb3: 0x158186f6f2dd04cfa4e78547 + }, + y0: u384 { + limb0: 0x9f1c7dcdbe4574f05d0c093b, + limb1: 0xcde395f3ee4e353cf25a2e21, + limb2: 0x6a44c4a6d642c3dd98128703, + limb3: 0x2bd32fdfe26d866771e2180 + }, + y1: u384 { + limb0: 0x7060005397ea11f7e9a26050, + limb1: 0xeb8540654b533da9b594fc27, + limb2: 0xfc83cf9d283b7231df1db3f9, + limb3: 0x7ff9623d918ca12e0ff6cce + } + }; + + q2.assert_on_curve(1); + let (tmp2) = miller_loop_bls12_381_tower(p2, q2); + let (res) = run_BLS12_381_E12T_MUL_circuit(tmp2, res); + let final = final_exp_bls12_381_tower(res); + assert_eq!( + final, + E12T { + c0b0a0: u384 { limb0: 0x1, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c0b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b0a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b1a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a0: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 }, + c1b2a1: u384 { limb0: 0x0, limb1: 0x0, limb2: 0x0, limb3: 0x0 } + } + ); + } + + + #[test] + fn test_tower_final_exp_BN254() { + let input = E12T { + c0b0a0: u384 { + limb0: 0x9558867f5ba91faf7a024204, + limb1: 0x37ebdcd9e87a1613e443df78, + limb2: 0x8e9dc4681332876, + limb3: 0x0 + }, + c0b0a1: u384 { + limb0: 0xfb97d43588561712e8e5216a, + limb1: 0x9a164106cf6a659eb4862b21, + limb2: 0x967d0cae6f4590b, + limb3: 0x0 + }, + c0b1a0: u384 { + limb0: 0xbad640fb19488dec4f65d4d9, + limb1: 0xd9b8a714e61a441c12e0c8b2, + limb2: 0x1521f387af19922a, + limb3: 0x0 + }, + c0b1a1: u384 { + limb0: 0x19c78df48f4ff31e78de5857, + limb1: 0x50f244556f25e2a25a921187, + limb2: 0x28fcb26f9c6316b9, + limb3: 0x0 + }, + c0b2a0: u384 { + limb0: 0xf77383c13458a748e9bb17bc, + limb1: 0x71545a137a1d50068d723104, + limb2: 0x215ddba6dd84f39e, + limb3: 0x0 + }, + c0b2a1: u384 { + limb0: 0xce164dba0ff18e0242af9fc3, + limb1: 0xea7e9d498c778ea6eb2083e6, + limb2: 0x5f82a8f03983ca8, + limb3: 0x0 + }, + c1b0a0: u384 { + limb0: 0x66194cb1d71037d1b83e90ec, + limb1: 0xc8f8e3d0d3290a4cb5d32b16, + limb2: 0x28045af9ab0c1681, + limb3: 0x0 + }, + c1b0a1: u384 { + limb0: 0x7e5b1e7f9ca5499d004ae545, + limb1: 0x55485822de1b372ad3fbf47a, + limb2: 0x2ebce25e3e70f16a, + limb3: 0x0 + }, + c1b1a0: u384 { + limb0: 0xded733e8b421eaeb534097ca, + limb1: 0xeac1c14f30e9c5cc101fbccc, + limb2: 0xe30658b9148624f, + limb3: 0x0 + }, + c1b1a1: u384 { + limb0: 0xf7b0b7d2cda8056c3d15eef7, + limb1: 0x8b0163c1cd9d2b7d247a8333, + limb2: 0x5d67b7072ae2244, + limb3: 0x0 + }, + c1b2a0: u384 { + limb0: 0x51ef1922fe43c49e149818d1, + limb1: 0xff7b118e820865d6e005b860, + limb2: 0x1f507980eece328b, + limb3: 0x0 + }, + c1b2a1: u384 { + limb0: 0x8d1fd9b74d2b9deb1beb3711, + limb1: 0x1ff39849b4e1357d4a84eb03, + limb2: 0x154bc8ce8c25166a, + limb3: 0x0 + } + }; + + let res = final_exp_bn254_tower(input); + assert_eq!( + res, + E12T { + c0b0a0: u384 { + limb0: 0xdbc3eb4cffd298b3fa7d5a31, + limb1: 0x9c46ca08e6740e40f6588c03, + limb2: 0x1e656501517e97b6, + limb3: 0x0 + }, + c0b0a1: u384 { + limb0: 0x5c5f9021ddc05b4e8e458180, + limb1: 0xfc9ac0db94ad84f883101197, + limb2: 0x10d35fc577ab954a, + limb3: 0x0 + }, + c0b1a0: u384 { + limb0: 0x8338823c5e5ac5cd9c54b10c, + limb1: 0x1749d62236197afa5b52b1b2, + limb2: 0xc2fb8c574d4a2aa, + limb3: 0x0 + }, + c0b1a1: u384 { + limb0: 0x3fed1e7b4d562acb92ab1a7c, + limb1: 0x215c21048e64e6366563b7bd, + limb2: 0x56befad9198c47f, + limb3: 0x0 + }, + c0b2a0: u384 { + limb0: 0x2e357f74fb161fde82246aaf, + limb1: 0x30461114e53b7faeeabde969, + limb2: 0x160bd4f153a876cc, + limb3: 0x0 + }, + c0b2a1: u384 { + limb0: 0x9953d9fc7152b696a117f008, + limb1: 0x3260659f2890ee7e7fef447, + limb2: 0x2c09cd97bcdf915f, + limb3: 0x0 + }, + c1b0a0: u384 { + limb0: 0x68db7596dac15cee7f675e5b, + limb1: 0xd64fc7fa279a306f05a4f7bb, + limb2: 0x1badb5f4113cf175, + limb3: 0x0 + }, + c1b0a1: u384 { + limb0: 0xd43446d44724e68a5d3e0ce0, + limb1: 0x1ad7eb734406471bac65ff96, + limb2: 0x15027bc7d1c7191b, + limb3: 0x0 + }, + c1b1a0: u384 { + limb0: 0x75668ecaf7e92d7d38d72226, + limb1: 0x2f055eefa07fed95961aa90e, + limb2: 0x231ea84923202c33, + limb3: 0x0 + }, + c1b1a1: u384 { + limb0: 0x5d2ac3131b5214c54a04b4ca, + limb1: 0x5a879571728f9d6a335a11b6, + limb2: 0x1a88b1de9b27f1fe, + limb3: 0x0 + }, + c1b2a0: u384 { + limb0: 0x1c3137fb1e4efedec89693d5, + limb1: 0x90787e810e0d14fcd37605c5, + limb2: 0x27a6e50c674c3d45, + limb3: 0x0 + }, + c1b2a1: u384 { + limb0: 0x36b1cc116e2ac5e8f8918e00, + limb1: 0xcb7e94a03ed3261502d9cf46, + limb2: 0xbec9af879f51f8, + limb3: 0x0 + } + } + ); + } + + + #[test] + fn test_tower_final_exp_BLS12_381() { + let input = E12T { + c0b0a0: u384 { + limb0: 0x4da5e709d4713d60c8a70639, + limb1: 0x5ba91faf7a024204f7c1bd87, + limb2: 0xe87a1613e443df789558867f, + limb3: 0x474ee238133287637ebdcd9 + }, + c0b0a1: u384 { + limb0: 0xc17c627923c6612f48268673, + limb1: 0xcca5a5a19e4d6e3c1846d424, + limb2: 0xe8e5216afcbd04c340212ef7, + limb3: 0x1690c564fb97d43588561712 + }, + c0b1a0: u384 { + limb0: 0xe6f4590b9a164106cf6a659e, + limb1: 0x19488dec4f65d4d9259f4329, + limb2: 0xe61a441c12e0c8b2bad640fb, + limb3: 0xa90f9c3af19922ad9b8a714 + }, + c0b1a1: u384 { + limb0: 0x19c78df48f4ff31e78de5857, + limb1: 0x50f244556f25e2a25a921187, + limb2: 0xe9bb17bca3f2c9bf9c6316b9, + limb3: 0x11ae4620f77383c13458a748 + }, + c0b2a0: u384 { + limb0: 0xdd84f39e71545a137a1d5006, + limb1: 0xff18e0242af9fc385776e9a, + limb2: 0x8c778ea6eb2083e6ce164dba, + limb3: 0x2fc154703983ca8ea7e9d49 + }, + c0b2a1: u384 { + limb0: 0x3e70f16a55485822de1b372a, + limb1: 0xb421eaeb534097cabaf3897a, + limb2: 0x30e9c5cc101fbcccded733e8, + limb3: 0x71832c59148624feac1c14f + }, + c1b0a0: u384 { + limb0: 0xeece328bff7b118e820865d6, + limb1: 0x4d2b9deb1beb37117d41e602, + limb2: 0xb4e1357d4a84eb038d1fd9b7, + limb3: 0xaa5e4678c25166a1ff39849 + }, + c1b0a1: u384 { + limb0: 0x8a5006c1ec188efbd080e66e, + limb1: 0xcca74147f6be1f723405095c, + limb2: 0x966e12778c1745a79a6a5f92, + limb3: 0x2eea66d71eacd0549a3e80e + }, + c1b1a0: u384 { + limb0: 0x6288e1a5cc45782198a6416d, + limb1: 0x3dfabc08935ddd725129fb7c, + limb2: 0x307bf3262f1205544a5308cc, + limb3: 0x10e1c2b2fcd81b5d24bace4 + }, + c1b1a1: u384 { + limb0: 0xa81ad477fb3675b89cdeb3e6, + limb1: 0x11af923d79fdef7c42930b33, + limb2: 0xc1f254b8adc0da7a16febaa0, + limb3: 0x4c91dc7e07405eb215663ab + }, + c1b2a0: u384 { + limb0: 0x151665705b7c709acb175a5a, + limb1: 0x1d878f9f9cdf5a865306f3f5, + limb2: 0xa1515607964a870c7c879b74, + limb3: 0x6179561d857010255d44936 + }, + c1b2a1: u384 { + limb0: 0xbb42e0b20426465e3e37952d, + limb1: 0xb490b6081dfc83524562be7f, + limb2: 0xcb69ca385f3f563838701a14, + limb3: 0xda2ddc3552116dd2ba4b180 + } + }; + + let res = final_exp_bls12_381_tower(input); + assert_eq!( + res, + E12T { + c0b0a0: u384 { + limb0: 0xc47661ee2c6ec195b6465492, + limb1: 0x6923c966026d1a5202d2547f, + limb2: 0x3ca333e30f3750a593c5dd62, + limb3: 0x16211c8f3af6c885d6e7aae7 + }, + c0b0a1: u384 { + limb0: 0x18ef376237b7b85323d0d503, + limb1: 0x6e98bbb5ebf752814d657668, + limb2: 0xf72474b60f257f5566c184d6, + limb3: 0x6298b60c51ccfdaa550d764 + }, + c0b1a0: u384 { + limb0: 0x348c2c399e7bd6de56256576, + limb1: 0xf4a77fefb18543958b97e185, + limb2: 0x5d0aab75be4368260e7d2ed9, + limb3: 0x158469853e297d165ee80a77 + }, + c0b1a1: u384 { + limb0: 0x72f3c5aec1469c18e1fdbce1, + limb1: 0x51ddbb4388643f1a6efaf631, + limb2: 0x34f1e1e014398ac114bd5c0, + limb3: 0x10e831545a67da3f9fdf361a + }, + c0b2a0: u384 { + limb0: 0xf0e118cc2ee8a943979abc0c, + limb1: 0x6e7b8556c21ea7bb63547b6d, + limb2: 0x4479c64648fd5135f004569a, + limb3: 0x9c3267b433303abded9ab0 + }, + c0b2a1: u384 { + limb0: 0xe5fa5528617a7773128a3a1f, + limb1: 0x6be496fac02353edcae1c79e, + limb2: 0x4f9bbd2d6d5199cbf179da1f, + limb3: 0x17f02c9ce45af7421efccde + }, + c1b0a0: u384 { + limb0: 0xd2192367be40c767eecd94f0, + limb1: 0x5a094323a3c2b121fc6db025, + limb2: 0xe70f56b994092e1f7d106f54, + limb3: 0x12ac5958b941614ac10d5ff6 + }, + c1b0a1: u384 { + limb0: 0x96dcae9f5d11d83ff8ee58e0, + limb1: 0x1539f36298c543196ff7521, + limb2: 0xf4f41990abca0c681a3221f6, + limb3: 0x11aa8e62757ec2cbf6c16ffc + }, + c1b1a0: u384 { + limb0: 0xffb243b8fb10435f6ea824db, + limb1: 0x1bda384d4058fd317cf9270f, + limb2: 0x3f176c05329fa1b37897428a, + limb3: 0x9ffc940d1185cb35015aa48 + }, + c1b1a1: u384 { + limb0: 0x74d71b12604949416f2e7fad, + limb1: 0x84b612cd1cafbc9b8af3e707, + limb2: 0xe4855dd3d16e5ae18223225e, + limb3: 0x801946300201b84e305ee6 + }, + c1b2a0: u384 { + limb0: 0xbb3b943ceffbff6187a09c3a, + limb1: 0x8c71050ce550d5e89695deb2, + limb2: 0x2fd70aa73c133a3e0e483ef2, + limb3: 0x7f835c51a9434870d20cedf + }, + c1b2a1: u384 { + limb0: 0xcb5beb0bdcff8c233260205d, + limb1: 0x987fe621d66e1a6dca01005b, + limb2: 0xf19f8ff647ec05851ed472a9, + limb3: 0x9f783e3dcba8af017c07469 + } + } + ); + } + + + #[test] + fn test_expt_half_BLS12_381() { + let input = E12T { + c0b0a0: u384 { + limb0: 0xe3ac2758b1f2a23159402205, + limb1: 0x776adf14829933202da5751a, + limb2: 0x5bace5b80e293dd7b75ca30d, + limb3: 0x275df6cfc4cc34ee2e1426f + }, + c0b0a1: u384 { + limb0: 0x6a1a0fac0380ab822cb9f49, + limb1: 0xf1a5da70f2bcb8f5e6d189b5, + limb2: 0xb9605d6164ac88b2e58734aa, + limb3: 0x6178fc2e2d96839d3ccabe6 + }, + c0b1a0: u384 { + limb0: 0xb343ef57150681832154ce9e, + limb1: 0x32d7b542146ded07806e3543, + limb2: 0xf0531ecdf071f340be23eb71, + limb3: 0x17bfe8e4c08234e0c2e85f61 + }, + c0b1a1: u384 { + limb0: 0x6a48ae9e0d45a65b46b124f0, + limb1: 0x22c3a45726890fc3e75712b9, + limb2: 0xa3e43a38db3ee9b2759e745f, + limb3: 0xb509ee1722d55991cbc266e + }, + c0b2a0: u384 { + limb0: 0x3e65e1d198488c5b45547fde, + limb1: 0x32b590108b32373abcc44192, + limb2: 0xb6c8b2c2cacad9bd22b87f0b, + limb3: 0x17341bebcfb46b3919e1140c + }, + c0b2a1: u384 { + limb0: 0xb9cab821cbd975c0ffdc67c8, + limb1: 0x844bfef770ab7fc0ff7c585e, + limb2: 0xc34fb405e0719e218adf4cda, + limb3: 0xb7d87719c2bab9241194b3d + }, + c1b0a0: u384 { + limb0: 0xc8de1b0b73c9757d8479766c, + limb1: 0xa5f030312159f381a92d1668, + limb2: 0x808b453867425d4ce92ab0ca, + limb3: 0xc98aa88897c0c6b2edc28db + }, + c1b0a1: u384 { + limb0: 0xb264c3a73b8175a6ee83c940, + limb1: 0x6a26e058e811ef6ad4df2948, + limb2: 0xb39592c43801e887c11cb17a, + limb3: 0xe67f58b04c48f601737c58c + }, + c1b1a0: u384 { + limb0: 0x4616073a64ebfc2e37d002b4, + limb1: 0xbcedb779f425f193e5a05990, + limb2: 0x3004f59b738b8cf2dacd9d, + limb3: 0x18510173ebccf15dcfb67bb4 + }, + c1b1a1: u384 { + limb0: 0x68785e9d2a8c1f3cd22b74c9, + limb1: 0xc13aa5c90a3964b3118e07ee, + limb2: 0xdd71679943a514616d96a409, + limb3: 0x5e9a73cd8bcc623956a00f0 + }, + c1b2a0: u384 { + limb0: 0xd054b25067025ef528684ca5, + limb1: 0xb98b233f22590428ff65e7e7, + limb2: 0x863f94e6f59dd2cc1b29aa15, + limb3: 0x40a30f80f41371306ace4d3 + }, + c1b2a1: u384 { + limb0: 0x82ff7f662c94e86e681d04bc, + limb1: 0x68fbbcb98776e529c74002eb, + limb2: 0xabac2de4cc82c3c718a21a75, + limb3: 0x8f53b1c2901726845866899 + } + }; + + let (res) = expt_half_bls12_381_tower(input); + assert_eq!( + res, + E12T { + c0b0a0: u384 { + limb0: 0x931e7dfdbe1f652c188eaa4b, + limb1: 0x82aaa351edc988786951ca9a, + limb2: 0x54412c1075ce2746c44fbaaa, + limb3: 0x194d674d95de505092e97747 + }, + c0b0a1: u384 { + limb0: 0xb22a60296aec52df8de3aa42, + limb1: 0x8be8af04ee32ae90e6f92ff0, + limb2: 0xdb264c1d022ccaa31f5f1e55, + limb3: 0x13c2c104d8418aa6c186c863 + }, + c0b1a0: u384 { + limb0: 0xf16f15e433e53d884ca450ae, + limb1: 0xbab8e1a90f84f24c7d8d7bb7, + limb2: 0x7c33ac5908cc4d224c8cb672, + limb3: 0x11c649a221098f0592d9e573 + }, + c0b1a1: u384 { + limb0: 0xa4ab60885ce8a47203eef11b, + limb1: 0x3de6b25ed023824c36351f47, + limb2: 0x257f17e0eeb3654697159a62, + limb3: 0xc742afcd12178eb714c25e4 + }, + c0b2a0: u384 { + limb0: 0x2db3c373e66b30e10f9f9d45, + limb1: 0x92e88c066844966e118c3c8d, + limb2: 0x16fd097082cf86fa0ee9b179, + limb3: 0x5c0754baecbd25ec3c53996 + }, + c0b2a1: u384 { + limb0: 0x21f88494e25abb2762bde18a, + limb1: 0x23a58e293f380741a2997a6f, + limb2: 0x76ea54dc279a3301a304e3e8, + limb3: 0x9f6038c6be05423ebd3e178 + }, + c1b0a0: u384 { + limb0: 0x18a242496526b14c50bed73d, + limb1: 0xc27c41f74df1b94a3b251ca4, + limb2: 0x147ca1df5c1a39cd188fe196, + limb3: 0x3a62857263f7afc342bdfee + }, + c1b0a1: u384 { + limb0: 0x357719d10ab8c0520084939d, + limb1: 0x50cfb756fa9f6a5b5a853d6d, + limb2: 0xcc89f28f2729e44b3d552e9b, + limb3: 0xb4601ced0c45e2775128a73 + }, + c1b1a0: u384 { + limb0: 0xba340a1342aeb93bc2367f71, + limb1: 0x1130eb422f714c3af0319aba, + limb2: 0x5411d9cdd1e37a8eb4a23883, + limb3: 0x58ca7e22399842e52f7e7ac + }, + c1b1a1: u384 { + limb0: 0xd91a1802a0ad0f168e57d558, + limb1: 0x3bb71c240214073cb08bb41f, + limb2: 0xc5406201fb75fb66ae611a4d, + limb3: 0x189532247da029ae9a0264af + }, + c1b2a0: u384 { + limb0: 0xe850c7a5f139c398a432d6e3, + limb1: 0xece47d0aaef590d0e590a168, + limb2: 0xd480c1d152ba8c62fc7ca716, + limb3: 0xa0f18b8c690d4e3461ee05a + }, + c1b2a1: u384 { + limb0: 0x76c2ba1ef05a96b90f9fdeb1, + limb1: 0xf777cac315947753c4e6f4a9, + limb2: 0x601635ad906b95586d6c73f9, + limb3: 0x90e534b3e561c1a32ac874c + } + } + ); + } +} diff --git a/src/src/utils/drand.cairo b/src/src/utils/drand.cairo index da775fe2..c06d74c8 100644 --- a/src/src/utils/drand.cairo +++ b/src/src/utils/drand.cairo @@ -6,15 +6,19 @@ use core::circuit::{ CircuitModulus, AddInputResultTrait, CircuitInputs, CircuitInputAccumulator }; use garaga::core::circuit::AddInputResultTrait2; -use garaga::definitions::{G1Point, G2Point, u384Serde}; +use garaga::definitions::{G1Point, G2Point, u384Serde, BLS_G2_GENERATOR}; use garaga::basic_field_ops::{u512_mod_bls12_381, is_even_u384}; use core::num::traits::Zero; use garaga::ec_ops::{ ec_safe_add, scalar_mul_g1_fixed_small_scalar, MSMHintSmallScalar, DerivePointFromXHint, FunctionFelt, msm_g1_u128 }; +use garaga::ec_ops_g2; use garaga::circuits::isogeny::run_BLS12_381_APPLY_ISOGENY_BLS12_381_circuit; use garaga::circuits::ec::run_ADD_EC_POINT_circuit; + +use garaga::single_pairing_tower::{miller_loop_bls12_381_tower, final_exp_bls12_381_tower}; + // Chain: 52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971 // Public Key: // G2Point(x=(2020076495541918814736776030432697997716141464538799718886374996015782362070437455929656164150586936230283253179482, @@ -182,15 +186,22 @@ fn round_to_message(round: u64) -> [u32; 8] { #[inline] -fn xor_u32_array(a: [u32; 8], b: [u32; 8]) -> [u32; 8] { +fn xor_u32_array_8(a: [u32; 8], b: [u32; 8]) -> [u32; 8] { let [a0, a1, a2, a3, a4, a5, a6, a7] = a; let [b0, b1, b2, b3, b4, b5, b6, b7] = b; return [a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3, a4 ^ b4, a5 ^ b5, a6 ^ b6, a7 ^ b7]; } +#[inline] +fn xor_u32_array_4(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + let [a0, a1, a2, a3] = a; + let [b0, b1, b2, b3] = b; + return [a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3]; +} + const POW_2_32: u128 = 0x100000000; const POW_2_64: u128 = 0x10000000000000000; -const POW_2_96: u128 = 0x100000000000000000000; +const POW_2_96: u128 = 0x1000000000000000000000000; fn u32_array_to_u256(d: [u32; 8]) -> u256 { let [d0, d1, d2, d3, d4, d5, d6, d7] = d; @@ -250,7 +261,7 @@ fn hash_to_two_bls_felts(message: [u32; 8]) -> (u384, u384) { let bi = compute_sha256_u32_array( input: array, last_input_word: I_DST_PRIME_LAST_WORD, last_input_num_bytes: 1 ); - let bi_xor_b0 = xor_u32_array(bi, b0); + let bi_xor_b0 = xor_u32_array_8(bi, b0); let mut array: Array = array![]; for v in bi_xor_b0.span() { @@ -263,7 +274,7 @@ fn hash_to_two_bls_felts(message: [u32; 8]) -> (u384, u384) { let bi_1 = compute_sha256_u32_array(array, I_DST_PRIME_LAST_WORD, 1); - let bi1_xor_b0 = xor_u32_array(bi_1, b0); + let bi1_xor_b0 = xor_u32_array_8(bi_1, b0); let mut array: Array = array![]; for v in bi1_xor_b0.span() { array.append(*v); @@ -274,7 +285,7 @@ fn hash_to_two_bls_felts(message: [u32; 8]) -> (u384, u384) { }; let bi_2 = compute_sha256_u32_array(array, I_DST_PRIME_LAST_WORD, 1); - let bi2_xor_b0 = xor_u32_array(bi_2, b0); + let bi2_xor_b0 = xor_u32_array_8(bi_2, b0); let mut array: Array = array![]; for v in bi2_xor_b0.span() { array.append(*v); @@ -527,15 +538,309 @@ fn map_to_curve_inner_final_not_quad_res( return G1Point { x: outputs.get_output(x_affine), y: outputs.get_output(y_affine) }; } +// The result of a timelock encryption over drand quicknet. +struct CipherText { + U: G2Point, + V: [u8; 16], + W: [u8; 16], +} + +// bytes("IBE-H2") (4 + 2 bytes) +const IBE_H2: [u32; 2] = [0x4942452d, 0x4832]; +// bytes("IBE-H4") (4 + 2 bytes) +const IBE_H4: [u32; 2] = [0x4942452d, 0x4834]; +const IBE_H3: [u32; 2] = [0x4942452d, 0x4833]; + +use core::circuit::conversions::{ + DivRemU96By32, DivRemU96By64, ConstValue, POW64, POW64_TYPED, NZ_POW64_TYPED, POW32, + POW32_TYPED, NZ_POW32_TYPED, +}; + +use core::internal::bounded_int::{BoundedInt, bounded_int_div_rem, DivRemHelper}; + +const POW80: felt252 = 0x100000000000000000000; +const NZ_POW80_TYPED: NonZero> = 0x100000000000000000000; +const POW16: felt252 = 0x10000; +const NZ_POW16_TYPED: NonZero> = 0x10000; + +const POW48: felt252 = 0x1000000000000; +const NZ_POW48_TYPED: NonZero> = 0x1000000000000; + + +const POW24: felt252 = 0x1000000; +const POW8: felt252 = 0x100; +type u64_bi = BoundedInt<0, { POW64 - 1 }>; +type u80_bi = BoundedInt<0, { POW80 - 1 }>; +type u48_bi = BoundedInt<0, { POW48 - 1 }>; +type u32_bi = BoundedInt<0, { POW32 - 1 }>; + +impl DivRemU64By32 of DivRemHelper> { + type DivT = BoundedInt<0, { POW32 - 1 }>; + type RemT = BoundedInt<0, { POW32 - 1 }>; +} + +impl DivRemU96By80 of DivRemHelper> { + type DivT = BoundedInt<0, { POW16 - 1 }>; + type RemT = BoundedInt<0, { POW80 - 1 }>; +} + +impl DivRemU80By48 of DivRemHelper> { + type DivT = BoundedInt<0, { POW32 - 1 }>; + type RemT = BoundedInt<0, { POW48 - 1 }>; +} + +impl DivRemU48By16 of DivRemHelper> { + type DivT = BoundedInt<0, { POW32 - 1 }>; + type RemT = BoundedInt<0, { POW16 - 1 }>; +} + +impl DivRemU32By16 of DivRemHelper> { + type DivT = BoundedInt<0, { POW16 - 1 }>; + type RemT = BoundedInt<0, { POW16 - 1 }>; +} + + +#[inline(always)] +pub fn append_u96_to_u32_array(ref array: Array, u: u96) { + let (u32_h, u64_l): (DivRemU96By64::DivT, DivRemU96By64::RemT) = bounded_int_div_rem( + u, NZ_POW64_TYPED + ); + let (u32_mid, u32_low): (DivRemU64By32::DivT, DivRemU64By32::RemT) = bounded_int_div_rem( + u64_l, NZ_POW32_TYPED + ); + let u32_hf: felt252 = u32_h.into(); + let u32_mf: felt252 = u32_mid.into(); + let u32_lf: felt252 = u32_low.into(); + array.append(u32_hf.try_into().unwrap()); + array.append(u32_mf.try_into().unwrap()); + array.append(u32_lf.try_into().unwrap()); +} +#[inline] +pub fn append_u384_be_to_u32_array(ref array: Array, u: u384) { + append_u96_to_u32_array(ref array, u.limb3); + append_u96_to_u32_array(ref array, u.limb2); + append_u96_to_u32_array(ref array, u.limb1); + append_u96_to_u32_array(ref array, u.limb0); +} + +const NZ_POW24_32: NonZero = 0x1000000; +const NZ_POW16_32: NonZero = 0x10000; +const NZ_POW8_32: NonZero = 0x100; + +#[inline(always)] +pub fn u32_to_u8_4(a: u32) -> [u8; 4] { + let (b3, r) = DivRem::div_rem(a, NZ_POW24_32); + let (b2, r) = DivRem::div_rem(r, NZ_POW16_32); + let (b1, b0) = DivRem::div_rem(r, NZ_POW8_32); + return [ + b3.try_into().unwrap(), + b2.try_into().unwrap(), + b1.try_into().unwrap(), + b0.try_into().unwrap() + ]; +} + + +#[inline(always)] +pub fn u32_4_to_u8_16(a: [u32; 4]) -> [u8; 16] { + let [a3, a2, a1, a0] = a; + let [b15, b14, b13, b12] = u32_to_u8_4(a3); + let [b11, b10, b9, b8] = u32_to_u8_4(a2); + let [b7, b6, b5, b4] = u32_to_u8_4(a1); + let [b3, b2, b1, b0] = u32_to_u8_4(a0); + return [b15, b14, b13, b12, b11, b10, b9, b8, b7, b6, b5, b4, b3, b2, b1, b0]; +} + +#[inline(always)] +pub fn append_u96_with_pending_u16(ref array: Array, pending_u16: u32, u: u96) -> u32 { + let (u16_h, u80_l): (DivRemU96By80::DivT, DivRemU96By80::RemT) = bounded_int_div_rem( + u, NZ_POW80_TYPED + ); + let (u32_mid, u48_low): (DivRemU80By48::DivT, DivRemU80By48::RemT) = bounded_int_div_rem( + u80_l, NZ_POW48_TYPED + ); + let (u32_low, u16_low): (DivRemU48By16::DivT, DivRemU48By16::RemT) = bounded_int_div_rem( + u48_low, NZ_POW16_TYPED + ); + let u16_hf: felt252 = u16_h.into(); + let u32_mf: felt252 = u32_mid.into(); + let u32_lf: felt252 = u32_low.into(); + let next_u16_pending: felt252 = u16_low.into(); + + array.append((pending_u16.into() * POW16 + u16_hf).try_into().unwrap()); + array.append(u32_mf.try_into().unwrap()); + array.append(u32_lf.try_into().unwrap()); + + return next_u16_pending.try_into().unwrap(); +} + + +#[inline(always)] +pub fn append_u32_with_pending_u16(ref array: Array, pending_u16: u32, u: u32) -> u32 { + let (u16_h, next_pending) = DivRem::div_rem(u, NZ_POW16_32); + let u16_hf: felt252 = u16_h.into(); + array.append((pending_u16.into() * POW16 + u16_hf).try_into().unwrap()); + return next_pending; +} + +pub fn append_u384_with_pending_u16(ref array: Array, pending_u16: u32, u: u384) -> u32 { + let pending_u16 = append_u96_with_pending_u16(ref array, pending_u16, u.limb3); + let pending_u16 = append_u96_with_pending_u16(ref array, pending_u16, u.limb2); + let pending_u16 = append_u96_with_pending_u16(ref array, pending_u16, u.limb1); + let pending_u16 = append_u96_with_pending_u16(ref array, pending_u16, u.limb0); + return pending_u16; +} + + +pub fn u8_16_to_u32_4(a: [u8; 16]) -> [u32; 4] { + let [a15, a14, a13, a12, a11, a10, a9, a8, a7, a6, a5, a4, a3, a2, a1, a0] = a; + let w3: felt252 = a15.into() * POW24 + a14.into() * POW16 + a13.into() * POW8 + a12.into(); + let w2: felt252 = a11.into() * POW24 + a10.into() * POW16 + a9.into() * POW8 + a8.into(); + let w1: felt252 = a7.into() * POW24 + a6.into() * POW16 + a5.into() * POW8 + a4.into(); + let w0: felt252 = a3.into() * POW24 + a2.into() * POW16 + a1.into() * POW8 + a0.into(); + return [ + w3.try_into().unwrap(), + w2.try_into().unwrap(), + w1.try_into().unwrap(), + w0.try_into().unwrap() + ]; +} + +pub fn decrypt_at_round(signature_at_round: G1Point, ciphertext: CipherText) -> [u8; 16] { + let (M) = miller_loop_bls12_381_tower(signature_at_round, ciphertext.U); + let rgid = final_exp_bls12_381_tower(M); + + let mut array: Array = array![]; + + let [ibe_h2_0, ibe_h2_1] = IBE_H2; + array.append(ibe_h2_0); + let pending = append_u384_with_pending_u16(ref array, ibe_h2_1, rgid.c1b2a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c1b2a0); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c1b1a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c1b1a0); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c1b0a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c1b0a0); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b2a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b2a0); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b1a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b1a0); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b0a1); + let pending = append_u384_with_pending_u16(ref array, pending, rgid.c0b0a0); + + let [r7, r6, r5, r4, _, _, _, _] = compute_sha256_u32_array( + input: array, last_input_word: pending, last_input_num_bytes: 2 + ); + + let v: [u32; 4] = u8_16_to_u32_4(ciphertext.V); + let sigma: [u32; 4] = xor_u32_array_4([r7, r6, r5, r4], v); + + let mut array: Array = array![]; + let [ibe_h4_0, ibe_h4_1] = IBE_H4; + array.append(ibe_h4_0); + + let [s3, s2, s1, s0] = sigma; + let pending = append_u32_with_pending_u16(ref array, ibe_h4_1, s3); + let pending = append_u32_with_pending_u16(ref array, pending, s2); + let pending = append_u32_with_pending_u16(ref array, pending, s1); + let pending = append_u32_with_pending_u16(ref array, pending, s0); + + let [sh7, sh6, sh5, sh4, _, _, _, _] = compute_sha256_u32_array( + input: array, last_input_word: pending, last_input_num_bytes: 2 + ); + + let w = u8_16_to_u32_4(ciphertext.W); + let message: [u32; 4] = xor_u32_array_4([sh7, sh6, sh5, sh4], w); + let [m3, m2, m1, m0] = message; + // Convert to bytes : + let message_bytes = u32_4_to_u8_16(message); + + // Verify U = G^R + + let mut array: Array = array![]; + let [ibe_h3_0, ibe_h3_1] = IBE_H3; + array.append(ibe_h3_0); + // Append sigma + let pending = append_u32_with_pending_u16(ref array, ibe_h3_1, s3); + let pending = append_u32_with_pending_u16(ref array, pending, s2); + let pending = append_u32_with_pending_u16(ref array, pending, s1); + let pending = append_u32_with_pending_u16(ref array, pending, s0); + // Append message : + let pending = append_u32_with_pending_u16(ref array, pending, m3); + let pending = append_u32_with_pending_u16(ref array, pending, m2); + let pending = append_u32_with_pending_u16(ref array, pending, m1); + let pending = append_u32_with_pending_u16(ref array, pending, m0); + + // Little endian + let rh = compute_sha256_u32_array( + input: array, last_input_word: pending, last_input_num_bytes: 2 + ); + + let mut i = 1; + let mut r = expand_message_drand(rh, i); + + // r must be non-zero: + while r == 0 { + i += 1; + let _r = expand_message_drand(rh, i); + r = _r; + }; + + let U = ec_ops_g2::ec_mul(BLS_G2_GENERATOR, r, 1).unwrap(); + assert(U == ciphertext.U, 'Incorrect ciphertext proof.'); + return message_bytes; +} + +pub fn expand_message_drand(msg: [u32; 8], i: u8) -> u256 { + let mut array: Array = array![]; + let [m7, m6, m5, m4, m3, m2, m1, m0] = msg; + // i.to_bytes(2, byteorder="little") + let pending = append_u32_with_pending_u16(ref array, i.into() * 0x100, m7); + let pending = append_u32_with_pending_u16(ref array, pending, m6); + let pending = append_u32_with_pending_u16(ref array, pending, m5); + let pending = append_u32_with_pending_u16(ref array, pending, m4); + let pending = append_u32_with_pending_u16(ref array, pending, m3); + let pending = append_u32_with_pending_u16(ref array, pending, m2); + let pending = append_u32_with_pending_u16(ref array, pending, m1); + let pending = append_u32_with_pending_u16(ref array, pending, m0); + + let hash_result = compute_sha256_u32_array( + input: array, last_input_word: pending, last_input_num_bytes: 2 + ); + + let [r0, r1, r2, r3, r4, r5, r6, r7] = hash_result; + + // Mask the first byte of r0 + // Extract the leftmost byte + let first_byte = r0 & 0xFF000000; + + // Right shift the first byte by 1 bit + let shifted_byte = first_byte / 2; + + // Combine the shifted byte back with the rest of r0 + let r0 = shifted_byte | (r0 & 0x00FFFFFF); + + return hash_to_u256([r0, r1, r2, r3, r4, r5, r6, r7]); +} + + +pub fn hash_to_u256(msg: [u32; 8]) -> u256 { + let [a, b, c, d, e, f, g, h] = msg; + let low: u128 = h.into() + g.into() * POW_2_32 + f.into() * POW_2_64 + e.into() * POW_2_96; + let high: u128 = d.into() + c.into() * POW_2_32 + b.into() * POW_2_64 + a.into() * POW_2_96; + + u256 { low: low, high: high } +} + #[cfg(test)] mod tests { use super::{ DRAND_QUICKNET_PUBLIC_KEY, hash_to_two_bls_felts, u384, G1Point, MapToCurveHint, map_to_curve, HashToCurveHint, MSMHintSmallScalar, DerivePointFromXHint, - hash_to_curve_bls12_381, FunctionFelt, run_BLS12_381_APPLY_ISOGENY_BLS12_381_circuit + hash_to_curve_bls12_381, FunctionFelt, run_BLS12_381_APPLY_ISOGENY_BLS12_381_circuit, + CipherText, decrypt_at_round, G2Point, }; - use garaga::ec_ops::{G2PointTrait}; + use garaga::ec_ops_g2::G2PointTrait; #[test] fn test_drand_quicknet_public_key() { @@ -829,5 +1134,113 @@ mod tests { let res = hash_to_curve_bls12_381(message, hint); assert_eq!(res, expected); } + + #[test] + fn test_decrypt_at_round() { + // msg: b'hello\x00\x00\x00\x00\x00\x00\x00\x00abc' + // round: 128 + // network: DrandNetwork.quicknet + + let signature_at_round: G1Point = G1Point { + x: u384 { + limb0: 0xc0bcbd3576ff11f14722cf6c, + limb1: 0xd452247305c00e921bd480d6, + limb2: 0x8b9980255afbf088406ce2e9, + limb3: 0x3783c94f8000028fa31f457 + }, + y: u384 { + limb0: 0x2b4d36d607cf825974c364b4, + limb1: 0x44cd6938390204bd3a17bf08, + limb2: 0x92d3ea3afc64bf69e6c4cf27, + limb3: 0x9ee7907fd3b11fa8ec81ccc + } + }; + + let ciph = CipherText { + U: G2Point { + x0: u384 { + limb0: 0x340fdd978d12a78af62a4938, + limb1: 0xf70620e8446a28e3d2071039, + limb2: 0xe08fd6ca0d6e9bdcb5dbf048, + limb3: 0x14fb6e4f383578999fe9250 + }, + x1: u384 { + limb0: 0x25a2b053807bd5aa950143b1, + limb1: 0x845c1664a97d715be868b2d2, + limb2: 0x5c1891819cbeaf9241827325, + limb3: 0x1db774cee6dd8860aad23b7 + }, + y0: u384 { + limb0: 0x941e76c3d4243c3a29eb37b6, + limb1: 0xeb7d54ef8c76445a546aa67e, + limb2: 0x945908b037be402a146d92cc, + limb3: 0x51401dcca71a5b8e961858 + }, + y1: u384 { + limb0: 0x83136ccccc82c994f1c19abe, + limb1: 0x638557d8f6ba3dbceffb0d86, + limb2: 0xd81843d33e29bd92ca715eca, + limb3: 0x12d802c5957e9cab6e1e8c82 + } + }, + V: [ + 0xa7, + 0x35, + 0xd6, + 0x12, + 0x47, + 0x88, + 0xc9, + 0x3f, + 0x2c, + 0xc4, + 0xdd, + 0xe5, + 0x5d, + 0x54, + 0x31, + 0x15 + ], W: [ + 0x7f, + 0x10, + 0x1c, + 0x52, + 0x8b, + 0xf7, + 0x63, + 0x15, + 0x57, + 0x8d, + 0x77, + 0x2e, + 0x79, + 0x3f, + 0x01, + 0x29 + ], + }; + let msg_decrypted = decrypt_at_round(signature_at_round, ciph); + assert( + msg_decrypted.span() == [ + 0x68, + 0x65, + 0x6c, + 0x6c, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x61, + 0x62, + 0x63 + ].span(), + 'wrong msg' + ); + } } diff --git a/tests/contracts_e2e/fixtures/devnet.py b/tests/contracts_e2e/fixtures/devnet.py index 7d414b2b..ac47e6cc 100644 --- a/tests/contracts_e2e/fixtures/devnet.py +++ b/tests/contracts_e2e/fixtures/devnet.py @@ -42,6 +42,8 @@ def get_start_devnet_command(devnet_port: int, fork_mode: bool = False) -> List[ "full", "--block-generation-on", "transaction", + "--request-body-size-limit", + "4089446", ] if fork_mode: diff --git a/tests/contracts_e2e/install_devnet.sh b/tests/contracts_e2e/install_devnet.sh index 91b5c58e..2d5e4796 100755 --- a/tests/contracts_e2e/install_devnet.sh +++ b/tests/contracts_e2e/install_devnet.sh @@ -3,7 +3,7 @@ set -e DEVNET_INSTALL_DIR="$(git rev-parse --show-toplevel)/tests/contracts_e2e/devnet/bin" DEVNET_REPO="https://github.com/0xSpaceShard/starknet-devnet-rs" -DEVNET_VERSION="v0.2.0-rc.3" +DEVNET_VERSION="v0.2.0" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then diff --git a/tests/hydra/circuits/test_ec.py b/tests/hydra/circuits/test_ec.py new file mode 100644 index 00000000..fb29b26a --- /dev/null +++ b/tests/hydra/circuits/test_ec.py @@ -0,0 +1,89 @@ +import pytest + +from garaga.definitions import CURVES, CurveID, G1Point, G2Point, get_base_field +from garaga.modulo_circuit import WriteOps +from hydra.garaga.precompiled_circuits.ec import BasicEC, BasicECG2 + + +@pytest.mark.parametrize("curve_id", [CurveID.BLS12_381]) +def test_double_point_g1(curve_id: CurveID): + g = G1Point.get_nG(curve_id, 1) + circuit = BasicEC("test", 1) + gxys = circuit.write_elements(g.to_pyfelt_list(), WriteOps.INPUT) + field = get_base_field(CurveID.BLS12_381) + A = CURVES[CurveID.BLS12_381.value].a + a = circuit.write_element(field(A)) + + resx, resy = circuit.double_point(gxys, a) + + got = G1Point( + resx.value, + resy.value, + curve_id, + ) + + expected = G1Point.get_nG(CurveID.BLS12_381, 2) + assert got == expected, f"{got} != {expected}" + + +@pytest.mark.parametrize("curve_id", [CurveID.BLS12_381]) +def test_add_point_g1(curve_id: CurveID): + g = G1Point.get_nG(curve_id, 1) + h = G1Point.get_nG(curve_id, 2) + circuit = BasicEC("test", 1) + gxys = circuit.write_elements(g.to_pyfelt_list(), WriteOps.INPUT) + hxys = circuit.write_elements(h.to_pyfelt_list(), WriteOps.INPUT) + + resx, resy = circuit.add_points(gxys, hxys) + + got = G1Point( + resx.value, + resy.value, + curve_id, + ) + + expected = G1Point.get_nG(curve_id, 3) + assert got == expected, f"{got} != {expected}" + + +@pytest.mark.parametrize("curve_id", [CurveID.BLS12_381]) +def test_double_point_g2(curve_id: CurveID): + # Arrange + g = G2Point.get_nG(CurveID.BLS12_381, 1) + circuit = BasicECG2("test", 1) + gxys = circuit.write_elements(g.to_pyfelt_list(), WriteOps.INPUT) + + # Act + resx, resy = circuit.double_point_a_eq_0((gxys[0:2], gxys[2:4])) + + # Assert + got = G2Point( + (resx[0].value, resx[1].value), + (resy[0].value, resy[1].value), + CurveID.BLS12_381, + ) + expected = G2Point.get_nG(CurveID.BLS12_381, 2) + assert got == expected, f"{got} != {expected}" + + +@pytest.mark.parametrize("curve_id", [CurveID.BLS12_381]) +def test_add_point_g2(curve_id: CurveID): + # Arrange + g = G2Point.get_nG(curve_id, 1) + h = G2Point.get_nG(curve_id, 2) + circuit = BasicECG2("test", 1) + gxys = circuit.write_elements(g.to_pyfelt_list(), WriteOps.INPUT) + hxys = circuit.write_elements(h.to_pyfelt_list(), WriteOps.INPUT) + + # Act + resx, resy = circuit.add_points((gxys[0:2], gxys[2:4]), (hxys[0:2], hxys[2:4])) + + # Assert + got = G2Point( + (resx[0].value, resx[1].value), + (resy[0].value, resy[1].value), + CurveID.BLS12_381, + ) + + expected = G2Point.get_nG(curve_id, 3) + assert got == expected, f"{got} != {expected}" diff --git a/tests/hydra/test_drand.py b/tests/hydra/test_drand.py index 30207213..47320274 100644 --- a/tests/hydra/test_drand.py +++ b/tests/hydra/test_drand.py @@ -1,14 +1,16 @@ import hashlib +import random import pytest -from garaga.definitions import CurveID, G2Point +from garaga.definitions import CurveID, G1G2Pair, G2Point from garaga.drand.client import ( DrandNetwork, digest_func, get_randomness, print_all_chain_info, ) +from garaga.drand.tlock import decrypt_at_round, encrypt_for_round from garaga.signature import hash_to_curve @@ -31,10 +33,7 @@ def test_drand_sig_verification(round_number: int): ) print("message", msg_point) - from garaga.definitions import G1G2Pair - - # Temp fix before we figure out correct deserialization of message point. - if ( + assert ( G1G2Pair.pair( [ G1G2Pair( @@ -45,20 +44,54 @@ def test_drand_sig_verification(round_number: int): curve_id=CurveID.BLS12_381, ).value_coeffs == [1] + [0] * 11 - ): - print("Signature verification passed") - elif ( - G1G2Pair.pair( - [ - G1G2Pair( - p=round.signature_point, q=G2Point.get_nG(CurveID.BLS12_381, 1) - ), - G1G2Pair(p=msg_point, q=chain.public_key), - ], - curve_id=CurveID.BLS12_381, - ).value_coeffs - == [1] + [0] * 11 - ): - print("Signature verification passed") - else: - print("Signature verification failed") + ), "Signature verification failed" + + +@pytest.mark.parametrize("round", list(range(1, 5)) + list(range(1000, 1005))) +def test_tlock_encrypt_decrypt(round: int): + random.seed(42) + chain_infos = print_all_chain_info() + network = DrandNetwork.quicknet + chain = chain_infos[network] + + master = chain.public_key + + msg = random.randbytes(16) + + ciph = encrypt_for_round(master, round, msg) + + chain = chain_infos[network] + beacon = get_randomness(chain.hash, round) + signature_at_round = beacon.signature_point + + msg_decrypted = decrypt_at_round(signature_at_round, ciph) + assert msg_decrypted == msg + + +@pytest.mark.parametrize("round", list(range(1, 5))) +def test_tlock_encrypt_same_message_gives_different_ciphertexts(round: int): + random.seed(42) + chain_infos = print_all_chain_info() + network = DrandNetwork.quicknet + chain = chain_infos[network] + + master = chain.public_key + + msg = b"0123456789abcdef" + + ciph1 = encrypt_for_round(master, round, msg) + ciph2 = encrypt_for_round(master, round, msg) + + assert ciph1.U != ciph2.U + assert ciph1.V != ciph2.V + assert ciph1.W != ciph2.W + + chain = chain_infos[network] + beacon = get_randomness(chain.hash, round) + signature_at_round = beacon.signature_point + + msg_decrypted1 = decrypt_at_round(signature_at_round, ciph1) + msg_decrypted2 = decrypt_at_round(signature_at_round, ciph2) + + assert msg_decrypted1 == msg + assert msg_decrypted2 == msg diff --git a/tools/make/bytecode_check.sh b/tools/make/bytecode_check.sh index 097478d8..1cd065e5 100755 --- a/tools/make/bytecode_check.sh +++ b/tools/make/bytecode_check.sh @@ -23,3 +23,9 @@ cd ../drand_quicknet scarb build bytecode_length=$(jq '.bytecode | length' ./target/dev/drand_quicknet_DrandQuicknet.compiled_contract_class.json) echo "Bytecode length DRAND: $bytecode_length" + + +cd ../risc0_verifier_bn254 +scarb build +bytecode_length=$(jq '.bytecode | length' ./target/dev/risc0_bn254_verifier_Risc0Groth16VerifierBN254.compiled_contract_class.json) +echo "Bytecode length RISC0: $bytecode_length" diff --git a/tools/make/setup.sh b/tools/make/setup.sh index bd500de1..9906bc3d 100755 --- a/tools/make/setup.sh +++ b/tools/make/setup.sh @@ -101,8 +101,8 @@ echo "All done!" # Check Scarb version and print warning if it's not cd src/ # To use the .tool-versions file with asdf. -if ! scarb --version | grep -q "2.8.2"; then - echo "Warning: Scarb is not installed or its version is not 2.8.2." +if ! scarb --version | grep -q "2.8.4"; then + echo "Warning: Scarb is not installed or its version is not 2.8.4." echo "Got: $(scarb --version)" - echo "Please install Scarb 2.8.2 before continuing. https://docs.swmansion.com/scarb/download.html" + echo "Please install Scarb 2.8.4 before continuing. https://docs.swmansion.com/scarb/download.html" fi