diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..f44b9ef --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,129 @@ +# Circle CI configuration file +# https://circleci.com/docs/ + +version: 2.1 + +commands: + pip-install: + description: Upgrade pip + steps: + - run: + name: Upgrade pip + command: | + python -m pip install --upgrade --user pip + python -m pip install --upgrade --user wheel + python -m pip install --upgrade --user setuptools + + install-dependencies: + steps: + - run: + name: Install dependencies + command: | + pip3 install pytest + pip3 install flatbuffers + + run-test: + steps: + - run: + name: Run test + command: | + echo 'export PYTHONPATH=$PWD/src' >> $BASH_ENV + pytest + + setup-nobackend: + steps: + - run: + name: Set nobackend backend + command: | + echo 'export PYSNARK_BACKEND=nobackend' >> $BASH_ENV + + setup-libsnark: + steps: + - run: + name: Set libsnark backend + command: | + pip3 install python-libsnark + echo 'export PYSNARK_BACKEND=libsnark' >> $BASH_ENV + + setup-zkinterface: + steps: + - run: + name: Set zkinterface backend + command: | + echo 'export PYSNARK_BACKEND=zkinterface' >> $BASH_ENV + + setup-qaptools: + steps: + - run: + name: Set qaptools backend + command: | + echo 'export PYSNARK_BACKEND=qaptools' >> $BASH_ENV + + setup-snarkjs: + steps: + - run: + name: Set snarkjs backend + command: | + npm install snarkjs + echo 'export PYSNARK_BACKEND=snarkjs' >> $BASH_ENV + +jobs: + test-nobackend: + docker: + - image: cimg/python:3.7 + steps: + - checkout + - pip-install + - install-dependencies + - setup-nobackend + - run-test + + test-libsnark: + docker: + - image: cimg/python:3.7 + steps: + - checkout + - pip-install + - install-dependencies + - setup-libsnark + - run-test + + test-zkinterface: + docker: + - image: cimg/python:3.7 + steps: + - checkout + - pip-install + - install-dependencies + - setup-zkinterface + - run-test + + test-qaptools: + docker: + - image: cimg/python:3.7 + steps: + - checkout + - pip-install + - install-dependencies + - setup-qaptools + - run-test + + test-snarkjs: + docker: + - image: cimg/python:3.7-node + steps: + - checkout + - pip-install + - install-dependencies + - setup-snarkjs + - run-test + +workflows: + version: 2 + build: + jobs: + - test-nobackend + - test-libsnark + - test-zkinterface + - test-qaptools + - test-snarkjs \ No newline at end of file diff --git a/.gitignore b/.gitignore index 376dadb..2220a72 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ examples/cubeint.py pysnark_ek pysnark_log pysnark_vk +computation.zkif +circuit.zkif diff --git a/examples/bench.py b/examples/bench.py index d795bf5..57a87b5 100644 --- a/examples/bench.py +++ b/examples/bench.py @@ -4,6 +4,7 @@ import pysnark.runtime from pysnark.runtime import PrivVal, LinComb, benchmark, guarded +from pysnark.boolean import LinCombBool from pysnark.branching import if_then_else, _while def count_ops(fn): @@ -53,7 +54,7 @@ def benchmark_lin_bl(fn): pysnark.runtime.bitlength = 7 op6 = count_ops(guarded(LinComb.ONE)(fn)) coef2 = (op5-op4)//2 - const2 = op4-3*coef + const2 = op4-3*coef2 if op6!=const2+7*coef2: raise AssertionError("benchmark_lin_bl: constraints not linear in bitlength") @@ -91,199 +92,4 @@ def several(lst): print("__truediv__ (const) ", benchmark_con_bl(lambda:LinComb.ONE/1)) print("__truediv__ (val) ", benchmark_con_bl(lambda:LinComb.ONE/LinComb.ONE)) -# def __floordiv__(self, other): -# """ Division with rounding """ -# return self.__divmod__(other)[0] -# -# def __mod__(self, other): -# if other&(other-1)==0: -# # this is faster for powers of two -# return LinComb.from_bits(self.to_bits()[:other.bit_length()-1]) -# -# return self.__divmod__(other)[1] -# -# def __divmod__(self, divisor): -# """ Division by public value """ -# -# if not is_base_value(divisor): return NotImplemented -# -# if divisor==0: raise ValueError("division by zero") -# -# quo = PrivVal(self.value//divisor) -# rem = PrivVal(self.value-quo.value*divisor) -# -# rem.assert_positive(divisor.bit_length()) -# if divisor&(divisor-1)!=0: rem.assert_lt(divisor) # not needed for powers of two -# quo.assert_positive() -# (self-divisor*quo-rem).assert_zero() -# -# return (quo,rem) -# -# def __pow__(self, other, mod=None): -# """ Exponentiation with public integral power p>=0 """ -# if mod!=None: raise ValueError("cannot provide modulus") -# if not is_base_value(other): return NotImplemented -# if other<0: raise ValueError("exponent cannot be negative", other) -# if other==0: return LinComb.ONE -# if other==1: return self -# return self*pow(self, other-1) -# -# def __lshift__(self, other): -# """ Left-shift with public value """ -# # TODO: extend to secret offset? -# if not is_base_ovalue(other): return NotImplemented -# return self*(1<=0, self, -self) -# -# def __invert__(self): -# # we do not want to do ~1=0 and ~0=1 since this is also not true for native ints -# raise NotImplementedError("Operator ~ not supported. For binary not, use 1-x") -# -# def __complex__(self): return NotImplemented -# def __int__(self): raise NotImplementedError("Should not run int() on LinComb") -# def __float__(self): return NotImplemented -# -# def __round__(self, ndigits=None): return NotImplemented -# def __trunc__(self): return NotImplemented -# def __floor__(self): return NotImplemented -# def __ceil__(self): return NotImplemented -# -# def assert_bool(self): -# add_constraint(self, 1-self, LinComb.ZERO) -# -# def assert_bool_unsafe(self): -# add_constraint_unsafe(self, 1-self, LinComb.ZERO) -# -# def to_bits(self, bits=bitlength): -# if (not ignore_errors) and (self.value<0 or self.value.bit_length()>bits): -# raise ValueError("value " + str(self.value) + " is not a " + str(bits) + "-bit positive integer") -# -# bits = [PrivVal((self.value&(1<>ix) for ix in range(bits)] -# for bit in bits: bit.assert_bool_unsafe() -# -# (self-LinComb.from_bits(bits)).assert_zero() -# -# return bits -# -# @classmethod -# def from_bits(cls, bits): -# return sum([biti*(1<>bitlength], check if it is positive. -# Note that this works on (bitlength+1)-length values so it works for -# __lt__, etc on bitlength-length values -# """ -# def check_positive(self, bits=bitlength): -# if (not ignore_errors) and self.value.bit_length()>bits: -# raise ValueError("value " + str(self.value) + " is not a " + str(bits) + "-bit integer") -# -# ret = PrivVal(1 if self.value>=0 else 0) -# abs = self.value if self.value>=0 else -self.value -# -# bits = [PrivVal((abs&(1<>ix) for ix in range(bits)] -# for bit in bits: bit.assert_bool_unsafe() -# -# # if ret==1, then requires that 2*self=self+sum, so sum=self -# # if ret==0, this requires that 0=self+sum, so sum=-self -# add_constraint(2*ret, self, self+LinComb.from_bits(bits)) -# -# return ret -# -# def assert_positive(self, bits=bitlength): -# self.to_bits(bits) -# -# def check_zero(self): -# ret = PrivVal(1 if self.value==0 else 0) -# -# wit = PrivVal(backend.fieldinverse(self.value+ret.value)) # add ret.value so always nonzero -# -# # Trick from Pinocchio paper: if self is zero then ret=1 by first eq, -# # if self is nonzero then ret=0 by second eq -# add_constraint_unsafe(self, wit, 1-ret) -# add_constraint_unsafe(self, ret, LinComb.ZERO) -# -# return ret -# -# def assert_zero(self): -# if (not ignore_errors) and self.value!=0: -# raise ValueError("Value " + str(self.value) + " is not zero") -# -# add_constraint(LinComb.ZERO, LinComb.ZERO, self) -# -# def assert_nonzero(self): -# if (not ignore_errors) and self.value==0: -# raise ValueError("Value " + str(self.value) + " is not zero") -# -# wit = PrivVal(backend.fieldinverse(self.value if self.value!=0 else 1)) -# add_constraint(self, wit, LinComb.ONE) \ No newline at end of file +print("LimCombBool (val) ", benchmark_con_bl(lambda:LinCombBool(LinComb.ONE))) \ No newline at end of file diff --git a/examples/kaplanmeier.py b/examples/kaplanmeier.py index af29ec2..6b51066 100644 --- a/examples/kaplanmeier.py +++ b/examples/kaplanmeier.py @@ -32,7 +32,8 @@ import pysnark.runtime -from pysnark.runtime import PrivVal, LinCombFxp +from pysnark.runtime import PrivVal +from pysnark.fixedpoint import LinCombFxp if __name__ == '__main__': # example batch of survival data from two populations diff --git a/pysnark/boolean.py b/pysnark/boolean.py new file mode 100644 index 0000000..5e13a18 --- /dev/null +++ b/pysnark/boolean.py @@ -0,0 +1,222 @@ +import pysnark.runtime +from pysnark.runtime import LinComb, ConstVal, PrivVal, PubVal, add_constraint + +""" +Support for Boolean values +Costs 1 constraint to convert a LinComb to a LinCombBool +""" + +class LinCombBool: + def __init__(self, lc, constrain=True): + """ + Constructs a LinCombBool + Costs 1 constraint + """ + if not isinstance(lc, LinComb): + raise RuntimeError("Wrong type for LinCombBool") + if not LinCombBool.is_boolean_value(lc.value): + raise ValueError("LinCombBool can only take Boolean values") + + # Add boolean constraint to circuit + if constrain: + add_constraint(lc, 1 - lc, LinComb.ZERO) + + self.lc = lc + + def val(self): + return self.lc.val() + + def __repr__(self): + return "{" + str(self.lc.value) + "}" + + @classmethod + def is_boolean_value(cls, val): + if val == 0 or val == 1 or val == True or val == False: + return True + return False + + @classmethod + def parse_boolean(cls, val): + if val == 0 or val == 1: + return val + if val == True: + return 1 + if val == False: + return 0 + raise ValueError("LinCombBool can only take Boolean values") + + @classmethod + def _ensurebool(cls, val): + if isinstance(val,LinCombBool): + return val + elif isinstance(val,LinComb): + if not LinCombBool.is_boolean_value(val.value): + raise ValueError("LinCombBool can only take Boolean values") + return LinCombBool(val) + elif isinstance(val, int): + if not LinCombBool.is_boolean_value(val): + raise ValueError("LinCombBool can only take Boolean values") + return LinCombBool(ConstVal(val)) + raise RuntimeError("Wrong type for LinCombBool") + + def __add__(self, other): + """ + Performs an arithmetic addition with an integer or a LinComb + Returns a LinComb + Costs 0 constraints + """ + return self.lc + other + + def __sub__(self, other): + """ + Performs an arithmetic subtraction by an integer or a LinComb + Returns a LinComb + Costs 0 constraints + """ + return self.lc - other + + def __mul__(self, other): + """ + Performs an arithmetic multiplication with an integer or a LinComb + Returns a LinComb + Costs 0 constraints to multiply with an integer + Costs 1 constraint to multiply with a LinComb + """ + return self.lc * (other) + + def __truediv__(self, other): + return NotImplemented + + def __floordiv__(self, other): + return NotImplemented + + def __mod__(self, other): + return NotImplemented + + def __divmod__(self, divisor): + return NotImplemented + + __radd__ = __add__ + __rmul__ = __mul__ + + def __rsub__(self, other): + """ + Performs an arithmetic subtraction by an integer or a LinComb + Returns a LinComb + Costs 0 constraints + """ + return other + (-self.lc) + + def __rtruediv__(self, other): + return NotImplemented + + def __neg__(self): + """ + Performs an arithmetic negation + Returns a LinComb + Costs 0 constraints + """ + return -self.lc + + def __invert__(self): + """ + Performs a logical not + Returns a LinCombBool + Costs 1 constraint + """ + return LinCombBool(1 - self.lc, False) + + def __and__(self, other): + """ + Performs a logical AND + Costs 0 constraints to AND with a constant + Costs 1 constraint to AND with a LinComb + """ + if isinstance(other, LinComb) or isinstance(other, LinCombBool): + other = LinCombBool._ensurebool(other) + return LinCombBool(self.lc * other.lc, False) + other = 1 if other else 0 + return LinCombBool(self.lc * other, False) + + def __xor__(self, other): + """ + Performs a logical XOR + Costs 0 constraints to XOR with a constant + Costs 1 constraint to XOR with a LinComb + """ + if isinstance(other, LinComb) or isinstance(other, LinCombBool): + other = LinCombBool._ensurebool(other) + return LinCombBool(self.lc + other.lc - 2 * self.lc * other.lc, False) + other = 1 if other else 0 + return LinCombBool(self + other - 2 * self * other, False) + + def __or__(self, other): + """ + Performs a logical OR + Costs 0 constraints to OR with a constant + Costs 1 constraint to OR with a LinComb + """ + if isinstance(other, LinComb) or isinstance(other, LinCombBool): + other = LinCombBool._ensurebool(other) + return LinCombBool(self.lc + other.lc - self.lc * other.lc, False) + other = 1 if other else 0 + return LinCombBool(self.lc + other - self.lc * other, False) + + def __eq__(self, other): return self.lc == self._ensurebool(other).lc + def __ne__(self, other): return self.lc != self._ensurebool(other).lc + def __lt__(self, other): return self.lc < self._ensurebool(other).lc + def __le__(self, other): return self.lc <= self._ensurebool(other).lc + def __gt__(self, other): return self.lc > self._ensurebool(other).lc + def __ge__(self, other): return self.lc >= self._ensurebool(other).lc + + def assert_eq(self, other, err=None): self.lc.assert_eq(self._ensurebool(other).lc) + def assert_ne(self, other, err=None): self.lc.assert_ne(self._ensurebool(other).lc) + def assert_lt(self, other, err=None): self.lc.assert_lt(self._ensurebool(other).lc) + def assert_le(self, other, err=None): self.lc.assert_le(self._ensurebool(other).lc) + def assert_gt(self, other, err=None): self.lc.assert_gt(self._ensurebool(other).lc) + def assert_ge(self, other, err=None): self.lc.assert_ge(self._ensurebool(other).lc) + + def __bool__(self): + raise NotImplementedError("Cannot call __bool__ on a LinComb. \ + Instead of if statements, use if_then_else from pysnark.branching") + + def __pow__(self, other, mod=None): + """ + Raises a LinCombBool to the power of an integer, LinComb, or LinCombBool + Returns a LinComb + Costs 2 constraints + """ + return self.lc != 0 + + def __lshift__(self, other): + return NotImplemented + + def __rshift__(self, other): + return NotImplemented + + def __pos__(self): + return self + + def __abs__(self): + return self.lc.__abs__() + + def __int__(self): + raise NotImplementedError("Should not run int() on LinCombBool") + + def check_positive(self): return self.lc.check_positive() + def assert_positive(self): self.lc.assert_positive() + def check_zero(self): return self.lc.check_zero() + def assert_zero(self): self.lc.assert_zero() + def assert_nonzero(self): self.lc.assert_nonzero() + +def PubValBool(val): + if not isinstance(val, int) and not isinstance(val, bool): + raise RuntimeError("Wrong type for PubValBool") + val = LinCombBool.parse_boolean(val) + return LinCombBool(PubVal(val)) + +def PrivValBool(val): + if not isinstance(val, int) and not isinstance(val, bool): + raise RuntimeError("Wrong type for PrivValBool") + val = LinCombBool.parse_boolean(val) + return LinCombBool(PrivVal(val)) \ No newline at end of file diff --git a/pysnark/branching.py b/pysnark/branching.py index a19a0c4..2ec3dfc 100644 --- a/pysnark/branching.py +++ b/pysnark/branching.py @@ -5,28 +5,31 @@ import pysnark.runtime -from .runtime import guarded, is_base_value, PubVal, PrivVal, ignore_errors, is_base_value, LinComb, add_guard, restore_guard - +from pysnark.runtime import guarded, is_base_value, PubVal, PrivVal, ignore_errors, is_base_value, LinComb, add_guard, restore_guard +from pysnark.boolean import LinCombBool +from pysnark.fixedpoint import LinCombFxp + def if_then_else(cond, truev, falsev): - if truev is falsev: return truev + if truev is falsev: + return truev - if is_base_value(cond): - if cond!=0 and cond!=1: - raise ValueError("not a boolean value: " + str(cond)) + if isinstance(cond, int): + if cond != 0 and cond != 1: + raise ValueError("if_then_else can only take Boolean values") return truev if cond else falsev - elif (not ignore_errors()) and cond.value!=0 and cond.value!=1: - raise(ValueError("not a bit: " + str(cond))) - else: - if callable(truev): truev = guarded(cond)(truev)() - if callable(falsev): falsev = guarded(1-cond)(falsev)() - - if isinstance(truev, list): - return [if_then_else(cond, truevi, falsevi) for (truevi,falsevi) in zip(truev,falsev)] - elif is_base_value(truev) or isinstance(truev, LinComb): - return falsev+cond*(truev-falsev) - else: - return truev.__if_then_else__(falsev, cond) + if not isinstance(cond, LinCombBool): + raise RuntimeError("Wrong type for if_then_else condition") + + if callable(truev): truev = guarded(cond)(truev)() + if callable(falsev): falsev = guarded(-cond)(falsev)() + + if isinstance(truev, list): + return [if_then_else(cond, truevi, falsevi) for (truevi,falsevi) in zip(truev,falsev)] + + if isinstance(truev, LinCombFxp): + falsev = LinCombFxp._ensurefxp(falsev) + return falsev + cond * (truev - falsev) class BranchingValues: def __init__(self): diff --git a/pysnark/fixedpoint.py b/pysnark/fixedpoint.py new file mode 100644 index 0000000..6691462 --- /dev/null +++ b/pysnark/fixedpoint.py @@ -0,0 +1,295 @@ +# Portions copyright (C) Meilof Veeningen, 2019 + +# Portions copyright (c) 2016-2018 Koninklijke Philips N.V. All rights +# reserved. A copyright license for redistribution and use in source and +# binary forms, with or without modification, is hereby granted for +# non-commercial, experimental and research purposes, provided that the +# following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimers. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimers in the +# documentation and/or other materials provided with the distribution. If +# you wish to use this software commercially, kindly contact +# info.licensing@philips.com to obtain a commercial license. +# +# This license extends only to copyright and does not include or grant any +# patent license or other license whatsoever. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import warnings +import pysnark.runtime +from pysnark.runtime import LinComb, PrivVal, PubVal, ConstVal, backend +from pysnark.boolean import LinCombBool + +""" +Support for fixed-point computations +Costs 0 constraints to convert a LinComb to a LinCombFxp +A float x is represented as the integer x * (1 << res) +""" + +# Fixed point resolution +resolution = 8 + +class LinCombFxp: + def __init__(self, lc, scale=True): + if not isinstance(lc, LinComb): + raise RuntimeError("Wrong type for LinCombFxp") + + # Add scaling if needed + if scale: + lc = LinCombFxp.add_scaling(lc) + + self.lc = lc + + @classmethod + def add_scaling(cls, val): + """ + Converts an integer, float, or LinComb into the internal fixed point representation + Does not convert the input into a LinCombFxp + """ + if isinstance(val, LinComb) or isinstance(val, LinCombBool): + return val * (1 << resolution) + if isinstance(val, int): + return val * (1 << resolution) + if isinstance(val, float): + res = val * (1 << resolution) + if res - int(res) != 0: + warnings.warn("Potential data loss due to low fixed point resolution") + return int(res) + raise RuntimeError("Wrong type for add_scaling") + + @classmethod + def remove_scaling(self, val): + """ + Converts an internal fixed point representation into a float value + """ + if isinstance(val, LinComb): + return float(val.val()) / (1 << resolution) + if isinstance(val, int) or isinstance(val, float): + return float(val) / (1 << resolution) + raise RuntimeError("Wrong type for add_scaling") + + def val(self): + return LinCombFxp.remove_scaling(self.lc.val()) + + def __repr__(self): + return "{" + str(self.lc.value) + "}" + + @classmethod + def _ensurefxp(cls, val): + """ + Converts an integer, float, or LinComb into the internal fixed point representation + and converts the input into a LinCombFxp + """ + if isinstance(val, LinCombFxp): + return val + if isinstance(val, LinComb): + return LinCombFxp(val) + if isinstance(val, LinCombBool): + return LinCombFxp(val.lc) + if isinstance(val, int) or isinstance(val, float): + val = LinCombFxp.add_scaling(val) + return LinCombFxp(ConstVal(val), False) + raise RuntimeError("Wrong type for LinCombFxp") + + def __add__(self, other): + """ + Adds a LinCombFxp with an integer, float, LinComb, or another LinCombFxp + Costs 0 constraints + """ + if isinstance(other, int) or isinstance(other, float) or isinstance(other, LinComb): + other = LinCombFxp.add_scaling(other) + return LinCombFxp(self.lc + other, False) + if isinstance(other, LinCombFxp): + return LinCombFxp(self.lc + other.lc, False) + return NotImplemented + + __radd__ = __add__ + + def __sub__(self, other): + """ + Subtracts a LinCombFxp by an integer, float, LinComb, or another LinCombFxp + Costs 0 constraints + """ + return self + (-other) + + def __rsub__(self, other): + return other + (-self) + + def __mul__(self, other): + """ + Multiplies a LinCombFxp with an integer, float, LinComb, or another LinCombFxp + Costs 0 constraints to multiply with an integer or a float + Costs 1 constraint to multiply with a LinComb + Costs 2 * bitlength + 5 constraint to multiply with a LinCombFxp + """ + if isinstance(other, int): + return LinCombFxp(self.lc * other, False) + if isinstance(other, float): + other = LinCombFxp.add_scaling(other) + return LinCombFxp((self.lc * other) // (1 << resolution), False) + if isinstance(other, LinComb): + return LinCombFxp(self.lc * other, False) + if isinstance(other, LinCombFxp): + return LinCombFxp((self.lc * other.lc) // (1 << resolution), False) + return NotImplemented + + __rmul__ = __mul__ + + def __truediv__(self, other): + """ + Divides a LinCombFxp with an integer, float, LinComb, or another LinCombFxp + Costs 2 * bitlength + 4 constraints to divide + """ + if isinstance(other, int): + return LinCombFxp(self.lc // other, False) + if isinstance(other, float): + other = LinCombFxp.add_scaling(other) + return LinCombFxp(self.lc * (1 << resolution) // other, False) + if isinstance(other, LinComb): + other = LinCombFxp.add_scaling(other) + return LinCombFxp(self.lc * (1 << resolution) // other, False) + if isinstance(other, LinCombFxp): + return LinCombFxp(self.lc * (1 << resolution) // other.lc, False) + return NotImplemented + + def __floordiv__(self, other): + """ + Divides LinCombFxp by an integer, float, LinComb, or LinCombFxp using floor division + Costs 2 * bitlength + 4 constraints for floor division + """ + res = self.__divmod__(other) + if res is NotImplemented: + return NotImplemented + return res[0] + + def __mod__(self, other): + """ + Returns the remainder of a LinCombFxp divided with an integer, float, LinComb, or LinCombFxp + Costs 2 * bitlength + 4 constraints for modular division + """ + res = self.__divmod__(other) + if res is NotImplemented: + return NotImplemented + return res[1] + + def __divmod__(self, divisor): + """ + Divides a LinCombFxp with an integer, float, LinComb, or LinCombFxp and returns the quotient and the remainder + Costs 2 * bitlength + 4 constraints to divide + """ + if isinstance(divisor, int) or isinstance(divisor, float) or isinstance(divisor, LinComb): + divisor = LinCombFxp.add_scaling(divisor) + res = self.lc.__divmod__(divisor) + elif isinstance(divisor, LinCombFxp): + res = self.lc.__divmod__(divisor.lc) + else: + return NotImplemented + if res is NotImplemented: + return NotImplemented + quo, rem = res + quo = LinCombFxp(quo) + rem = LinCombFxp(rem, False) + return (quo,rem) + + def __rtruediv__(self, other): + other = LinCombFxp._ensurefxp(other) + return other.__truediv__(self) + + def __rfloordiv__(self, other): + other = LinCombFxp._ensurefxp(other) + return other.__floordiv__(self) + + def __rmod__(self, other): + other = LinCombFxp._ensurefxp(other) + return other.__mod__(self) + + def __neg__(self): + return LinCombFxp(-self.lc, False) + + def __lt__(self, other): return self.lc < self._ensurefxp(other).lc + def __le__(self, other): return self.lc <= self._ensurefxp(other).lc + def __eq__(self, other): return self.lc == self._ensurefxp(other).lc + def __ne__(self, other): return self.lc != self._ensurefxp(other).lc + def __gt__(self, other): return self.lc > self._ensurefxp(other).lc + def __ge__(self, other): return self.lc >= self._ensurefxp(other).lc + + def assert_lt(self, other, err=None): self.lc.assert_lt(self._ensurefxp(other).lc) + def assert_le(self, other, err=None): self.lc.assert_le(self._ensurefxp(other).lc) + def assert_eq(self, other, err=None): self.lc.assert_eq(self._ensurefxp(other).lc) + def assert_ne(self, other, err=None): self.lc.assert_ne(self._ensurefxp(other).lc) + def assert_gt(self, other, err=None): self.lc.assert_gt(self._ensurefxp(other).lc) + def assert_ge(self, other, err=None): self.lc.assert_ge(self._ensurefxp(other).lc) + + def __bool__(self): return bool(self.lc) + + def __pow__(self, other, mod=None): + """ + Raises a LinCombFxp to the power of an integer + Costs 8 * bitlength + 20 constraints to take an exponent + """ + if mod != None: + raise ValueError("cannot provide modulus") + if not isinstance(other, int): + return NotImplemented + if other < 0: + raise ValueError("exponent cannot be negative", other) + if other == 0: + return LinCombFxp(LinComb.ONE) + if other == 1: + return self + + res = self * self ** (other - 1) + res.lc.value %= backend.get_modulus() + + return res + + def __lshift__(self, other): return LinCombFxp(self.lc<>other, False) + + def __pos__(self): + return self + + def __abs__(self): + from .branching import if_then_else + return if_then_else(self >= 0, self, -self) + + def __int__(self): raise NotImplementedError("Should not run int() on LinComb") + + def check_positive(self): return self.lc.check_positive() + def assert_positive(self): self.lc.assert_positive() + def check_zero(self): return self.lc.check_zero() + def check_nonzero(self): return self.lc.check_nonzero() + def assert_zero(self): self.lc.assert_zero() + def assert_nonzero(self): self.lc.assert_nonzero() + def assert_range(self, minrange, maxrange): + minrange = LinCombFxp._ensurefxp(minrange) + maxrange = LinCombFxp._ensurefxp(maxrange) + self.lc.assert_range(minrange.lc, maxrange.lc) + +def PubValFxp(val, doconvert=True): + if not isinstance(val, int) and not isinstance(val, float): + raise RuntimeError("Wrong type for PubValFxp") + if doconvert: + val = LinCombFxp.add_scaling(val) + return LinCombFxp(PubVal(val), False) + +def PrivValFxp(val, doconvert=True): + if not isinstance(val, int) and not isinstance(val, float): + raise RuntimeError("Wrong type for PrivValFxp") + if doconvert: + val = LinCombFxp.add_scaling(val) + return LinCombFxp(PrivVal(val), False) \ No newline at end of file diff --git a/pysnark/hash.py b/pysnark/ggh_hash.py similarity index 100% rename from pysnark/hash.py rename to pysnark/ggh_hash.py diff --git a/pysnark/nobackend.py b/pysnark/nobackend.py index 7bdf06a..fe74f13 100644 --- a/pysnark/nobackend.py +++ b/pysnark/nobackend.py @@ -20,10 +20,10 @@ def fieldinverse(val): return 0 def get_modulus(): - return 1 + return 10000 def add_constraint(v, w, y): pass def prove(): - pass \ No newline at end of file + pass diff --git a/pysnark/poseidon_constants.py b/pysnark/poseidon_constants.py new file mode 100644 index 0000000..b9e852c --- /dev/null +++ b/pysnark/poseidon_constants.py @@ -0,0 +1,322 @@ +# Poseidon constants from reference implementation +# TODO: Handle more backends +# TODO: Generate constants rather than using hardcoded values + +poseidon_constants = { + "zkinterface": { + "R_F": 8, + "R_P": 60, + "t": 5, + "a": 5, + "round_constants": [[0x0eb544fee2815dda7f53e29ccac98ed7d889bb4ebd47c3864f3c2bd81a6da891, 0x0554d736315b8662f02fdba7dd737fbca197aeb12ea64713ba733f28475128cb, 0x2f83b9df259b2b68bcd748056307c37754907df0c0fb0035f5087c58d5e8c2d4, 0x2ca70e2e8d7f39a12447ac83052451b461f15f8b41a75ef31915208f5aba9683, 0x1cb5f9319be6a45e91b04d7222271c94994196f12ed22c5d4ec719cb83ecfea9], \ + [0x2eb4f99c69f966ebf8a42192de7ff61621c7bb47b93750c2b9ea08d18446c122, 0x224a28e5a35385a7c5198169e405d9ea0fc7da8b93ee13b6d5f7d099e299520e, 0x0f7411b465e600eed8afdd6afca49c3036f33ecbd9a0f97823796b993bbd82f7, 0x0f9d0d5aad2c9555a2be7150392d8d9819b208ae3370f99a0626f9ff5d90e4e3, 0x1e9a96dc8292bb596f52a59538d329229732b25259cf744b6a12d30702d6fba0], \ + [0x08780514ccd90380887d578c45555e593cfe52eab4b945c6c2cd4d528fb3fe3c, 0x272498fced686c7ac8149fa3f73ef8c2ced64717e3556d5a59f119d629ccb5fc, 0x01ef8f9dd7c93aac4b7cb80930bd06eb45bd350aff585f10e3d0ef8a782ef7df, 0x045b9f59b6595e614dc08f222b469b138e886e64bf3c40aa97ea0ae754934d30, 0x0ac1e91c57d9da919fd6f59d2a40ff8ea3e41e24e247a387adf2584295d61c66], \ + [0x028a1621a94054b0c7f9a421353cd89d0fd67061aee99979d12e68f04e62d134, 0x26b41802c071ea4c9632647ed059236e50c19c3fb3c96d09d02aae2a0dcd9dbc, 0x2fb5dda8072bb72cbaac2f63e468215e05c9de06758db6a94af34384aedb462b, 0x2212d3a0f5fccaf244ff3547fd823249ad8ab8ba2a18d383dd05c56ee894d850, 0x1b041ad5b2f0684258e4dfaeea09be56a3276fdb19f44c015cd0c7eed465e2e3], \ + [0x0a01776bb22f4b6b8eccff33e76fded3144fb7e3ac14e846a91e64afb1500eff, 0x2b7b5674aaecc3cbf34d3f275066d549a4f33ae8c15cf827f7936440810ace43, 0x29d299b80cd4489e4cf75779ed54b48c60b042257b78fc004c1b803381a3bdfd, 0x1c46831d9a74529357641c219d721a74a427110032b5e1dd19dde30424be401e, 0x06d7626c953ccb72f37141dc34d578e036296c0657674f80739ae1d883e91269], \ + [0x28ffddc86f18c136c54002748e0c410edc5c440a3022cd960f108c71cda2930c, 0x2e67f7ee5e4aa295f85deed09e400b17be67f1b7ed2ab6adb8ec0619f6fbc5e9, 0x26ce38fa636c90630e97f25114a79a2dca56859ef759e53ce7abf22c24e80f27, 0x2e6e07c3c95bf7c34dd7a01d00a7ffec42cb3d16a1f72721afacb4c4cfd35db1, 0x2aa74f7597f0c9f45f91d7961c3a54fb8890d276612e1246384b1470da24d8cc], \ + [0x287d681a46a2faae2c7c090f668ab45b8a71313c1509183e2ec0ca639b7f73fe, 0x212bd19df812eaaef4a40600528f3d7da5d3106ff565aa3b11e29f3305e73c04, 0x1154f7cf519186bf1aafb14b350eb860f97fd9740926dab93809c28404713504, 0x1dff6385cb31f1c24637810a4bd1b16fbf5152905be36583da747e79661fc207, 0x0e444582d22b4e76c081d34c44c18e424011a34d5476252863ea3c606b551e5c], \ + [0x0323c9e433ba66c4abab6638328f02f1815773e9c2846323ff72d3aab7e4eff8, 0x12746bbd71791059193bba79cdec448f25b8cf002740112db70f2c6876a9c29d, 0x1173b7d112c2a798fd9b9d3751842c75d466c837cf50d73efd049eb4438a2240, 0x13d51c1090a1ad4876d1e555d7fed13da8e5713b25026ebe5fdb4808703243da, 0x00874c1344a4ad51ff8dcb7cbd2d9743cb72743f0394efe7f4a58ebeb956baa1], \ + [0x22df22131aaab85865ce236b07f244fa0eea48d3546e97d6a32a562074fef08f, 0x0bf964d2dbd25b908708b437a445fc3e984524a59101e6c18bf5eb05a919f155, 0x09b18d9b917a55bca302be1f7f181e0e640b9d73a9ab298c69b435b5fc502f32, 0x094f5534444fae36a4bfc1d5bf3dc05bfbbbc70a6365366dd6745a5067289e43, 0x2999bab1a5f25210519fa6622af53a15a3e240c0da5701cb784fddc0dc23f01f], \ + [0x2f6898c07581f6371ca94db73710e88084301bce8a93d13669575a11b03a3d23, 0x07268eaaba08bc19ec16d7e1318a4740565deb1e8e5742f862174b1a6866fccb, 0x186279b003454db01339ff77113bc9eb62603e078e1c6689a6c9582c41a0529f, 0x18a3f736509197d6e4915bdd04d3e5ddb67e2cc5de9a22750768e5524737172c, 0x0a21fa1988cf38d877cc1e2ed24c808c725e2d4bcb2d3a007b5987b87085671d], \ + [0x15b285cbe26c467f1faf5ef6a64625228328c184a2c43bc00b36a135e785fba2, 0x164b7062c4671cf08c08b8c3f9806d560b7775b7c902f5788cd28de3e779f161, 0x0890ba0819ac0a6f86d9865fe7e50ef361c61d3d43b6e65d7a24f651249baa70, 0x2fbea4d65d7ed425a42712e5a721e4eaa627ac5cb0eb878ccc2ee0aed543e922, 0x0492bf383c36fa55540303a3b536f85e7b70a58e854ab9b9103d7f5f379abaaa], \ + [0x05e91fe944e944104e20251c565142d61d6185a9ce85675f6a969d56292dc24e, 0x12fe5c2029e4b33893d463cb041acad0995b9621e6e49c3b7e380a76e36e6c1c, 0x024154adf0255d47958f7723921474131f2629fadc89496906cd01dc6fa0784e, 0x18824a09e6afaf4a36ed2462a86bd0bad798815644f2bbde8813c13457a45550, 0x0c8b482dba0ad51be9f255de0c3dbddddf84a630af68d50bbb06983e3d5d58a5], \ + [0x17325fd0ab635871363e0a1667d3b67c5a4fa67fcd6aaf86441392878fdb05e6, 0x050ae95f6d2f1519122f5af67b690f31e550773fa8d18bf71cc6d0e911fa402e, 0x0f0d139a0e81e943038cb288d62636764bbb6295f07569885771ec84edc50c40, 0x1c0f8697795689cdf70fd2f2c0f93d1a79b39ebc7a1b1c549dbbca7b8e747cd6, 0x2bd0f940ad936b796d2bc2e048bc979e49be23a4b13598f9fe536a16dc1d81e6], \ + [0x27eb1be27c9c4e934778c09a0053337fa06ebb275e096d167ce54d1e96ee62cb, 0x2e4889d830a67e5a8f96bdd3155a7ca3284fbd307d1f71b0f151be62548e2aea, 0x193fe3db0ab47d3c5d2ec5e9c5bd9983c9891f2cadc165db6064bbe6fcc1e305, 0x2bf3086e96c36c7bce415907ad0c40ed6e9661c009679e4e37cb13027c83e525, 0x12f16e2de6d4ad46a98cdb697c6cad5dd5e7e413f741ccf29ff2ea486e59bb28], \ + [0x2a72147d230119f3a0262e3653ddd19f33f3d5d6ec6c4bf0ad919b0343b92d2f, 0x21be0e2c4bfd64e56dc47f957806dc5f0a2d9bcc26412e2977df79acc10ba974, 0x0e2d7e1dc946d70b2749a3b54367b25a71b84fb911aa57ae137fd4b6c21b444a, 0x2667f7fb5a4fa1246170a745d8a4188cc31adb0eae3325dc9f3f07d4b92b3e2e, 0x2ccc6f431fb7400730a783b66064697a1550c12b08dfeb72830e107da78e3405], \ + [0x08888a94fc5a2ca34f0201462420001fae6dbee9e8ca0c242ec50621e38e6e5d, 0x02977b34eeaa3cb6ad40dd42c9b6fdd7a0d2fbe753af88b36acfcd3ccbc53f2a, 0x120ccce13d28b75cfd6fb6c9ea13a648bfcfe0d7e6ff8e9610b5e9f971e16b9a, 0x09fad2269c4a8e93c81e1b9770ea098c92787a4575b2bd73a0bf2af32f86ff3c, 0x026091fd3d4c44d50a4b310e4ac6f0fa0debdb70775eeb8af630cffb60092d6f], \ + [0x29404aa2ba565b77bb7fba9dfb6fc3212543cc56afad6afcb904fd2bca893994, 0x2749475c399aaf39d4e87c2548695b4ef1ffd86590e0827de7201351b7c883f9, 0x098c842322479f7239912b50424685cba2ebe2dc2e4da70ac7557dab65ffa222, 0x18cef581222b647e31238e57fead7d5c758ace14c93c4da40191d0c053b51936, 0x13177839c68a5080d4e746745e43711d3cbc0ca4a108f98d63b2aa681698de60], \ + [0x020ca696f531e43ec088f56f4b74325626cc4df712c0e5f0a907d88e5f0deffd, 0x27230eede9cccfc9fa805a30fc548db693d13708c646841d16e028387c7ac022, 0x01645911c1198b01d64fde34a342a1786497c05969a015439057d2fe75bb281c, 0x2c323fe16481bf496e439c88341ce25f198971e14487056cfdca4a451a5d8643, 0x0fc082dfe70728e8450bd2074c3e22e1b022c124d3bffe8b5af88ae6db5085c8], \ + [0x2052c174800db209d8cdca568dcc25b3be9642116ac4c77efe8a488b423521ee, 0x28e420e10df2fbb5af96d621d55423190be351ce8129065a8dd9fd05b3ece9c0, 0x25698ca5e24a1b799f783c4462a24db655d6ae1bdacd1cb549d6e0bc3ae5069a, 0x160a9981a5c89a57cf8ffbfa57d51049a297b61074422ac134d9b857d6984d35, 0x21c91a39e145c3bc34d9b694b843f3bf8b7cebf59ddbb0a064642b069997f3d4], \ + [0x1ac8d80dcd5ee876d2b09345ef112345d6eaa029d93f03b6d10975461e41734c, 0x0ab3e6ad0ecf8b8e7c1662a4174c52225d822895e2755544b8dbcea5657ce02c, 0x1c675182512620ae27e3b0b917b3a21ca52ef3ef5909b4e1c5b2237cbdab3377, 0x2cdbc998dfd7affd3d948d0c85bad2e2e37a4a3e07a7d75d0c8a9092ac2bed45, 0x23b584a56e2117b0774bf67cc0dee33324337350309dff833e491a133bb63b2e], \ + [0x1e9e2b310f60ba9f8cb73030a3c9d2a10d133bc6ba4ec1152f3d20de1465e9a5, 0x0e01e365ba5b3031abc3e720140ae746c9ab5dab987520c460bcd4f1fa5b22db, 0x040884cdcfc64bfc7b7127340498d5c443382011b61c9a4b1387d85bc1264e68, 0x190b1ee1205eb9500c74a3998f2bea36353f1724d6067ed0a0a17de311ef9668, 0x1647c72aec6c4388d04f52fc23cd9c08c1dfcf65ce61e165fc28d1f832bd3b2c], \ + [0x2430006346a0145f799880cc4c8736269f5494d89fb48b02842e595b71e4541d, 0x177b9a08343917e1365107a3da3ae7f69d853902bb16bacb3221850252b757af, 0x04a420e642b11ae94e58862a68f5e32609cd53d0ae29423439b11d04666df4f8, 0x25d0e0f739fb39fc105a88fab0afd810de2461858e956ccccdfabeddb6a25c8f, 0x04476d91b7eff2fd85905cbf58651edc320cb15610eaed452c4d4ffa0c740a27], \ + [0x1090c0b68b3d7d7b8bc9ca2419eb8dea1c28f6d5e1250cb5e9780fd9ca286fae, 0x25393ce3b9256d50448a725c5c7cd5ad376f2d435855c10ebf2899cb5c6617be, 0x25931c0c7371f4f1fc862f306e6e5830ed824388d6b9342697d144f0fab46630, 0x2396cb501700bbe6c82aad51b0fb79cf8a4d353185d5808203f73f22afbf62f6, 0x26a363483348b58954ea748a7129a7b0a3dc9068c3cca7b5b3f0ce03b8724884], \ + [0x27ca107ca204f2a18d6f1535b92c5478c99b893334215f6ba7a0e5b45fcd6897, 0x26da28fc097ed77ce4662bde326b2cceac15f7301178581d8d2d02b3b2d91056, 0x056ab351691d8bb3703e3055070ac9cc655774c1bb35d57572971ba56ee0cb89, 0x2638b57f23b754aec76d109a2f481aa3c22547a11ffc50152d729af632376a90, 0x304754bb8c57d60732f492c2605184fdc33e46a532bdec80ea7bc5519ede7cef], \ + [0x00d1727f8457ee03514f155b5806cbf748ec6857fc554010752ac93a9b7619ac, 0x00ee1f3c66fbc05c43ba295a303c72fab5bca86805ec9419c588e50947761fa3, 0x0afafadcf5b4dd4a4a76b5a1d82415fd10a19fbcfc59078c61f9297eb675d972, 0x0b2449f39746085e86ce45e8eed108ee65a234835a0a6a5ea8996d124dd04d0a, 0x206b0ce2f1b2c5b7c9f37b0045227095f6c6f071ec3bdda76a7ddf4823dd5dd6], \ + [0x0feba4fb87834c7cb696e67433628cd6caffc3a4ef20fea852c7e1029459409c, 0x254dbfac74c49b0b8926752e084e02513b06f1315e6d70e18173e972336e55d3, 0x0addb1372cee4e164655168c367559e19606c5bd17910aeb37719edfa0ca8762, 0x26b25b7e257f3e97c799024fb019f65c6ca4d8d81b1ae16221a589d68831d759, 0x090995b79acec240413b8d4c658787e5a4657b9ab00bdb5b1960b1059e113ba3], \ + [0x08dbdc2e21ef11f2c57299687843cea3eb0d8e40e99131f42974178d44f73b7b, 0x09e8aba671481197679faf752a0f78e342fe9c491596ab6758f170939785179f, 0x1deb05180e833e45659052a7ebaf816c7efd12a7f9eec94b7bc7c683f1363d5c, 0x19a70ec6bdfc9098a926efbcc04aa9ee248997e8b2c24af335fd6523e5250879, 0x21d773660adafb8a879986f9aab4890566353a3777d8a3f1eb93abe10bbf1f64], \ + [0x09f1890f72e9dc713e20ba637b89d5d397a6b01fcd667347f6f46617841c3901, 0x05af459361eb454d2a300c61e446998d48fa1f897bf219d608c2145c33b111c3, 0x0fa1a1d6829f0345664a66dc75a657335f336f15f340756cfa12fc850cc8b513, 0x02e47a35bcc0c3a0bda0b1c0307ad543f4280fcf87f636f853655cf97a628bb0, 0x14f773e9834c6bdeb8f90e78bf4c24b7203411460112491036621895204d0f12], \ + [0x102d98cf502ed843255cf19d29bc7d8e642abe7cfd639992ffb091962fc8f7cc, 0x043dd5f4aa5a76dd4c47f6c65da7ca2320d4c73ad3294738cba686a7e91373c2, 0x21833819c3337194a6c0d29a48d4f2676f0e7c79743a306f4cfdb2b26bd11efa, 0x0f281925cf5ee649b474a6819d116ca3eb4eca246c311ecadc53262a3cff2b53, 0x0d3e2477a7b10beb44709c7746d6824edf625dd60504d5dc93ce662f15c238d6], \ + [0x2cd7f641bedbf66956ff8a01be9cde35d80f80ab51e73b49acbfc3eff5aefc44, 0x29e95b492bf2f95f4d09380f98b74e389149d24045811d7a86dd861310463cf8, 0x22da66bc62e8f011266efca86a6c810f9ae4c51af6ffeb57f8b3c50df83cc13e, 0x0fe6d30de7a82d163023491794f4aca3220db79e8129df3643072d841925554a, 0x0050e842a1299909123c46eff185c23ad312d03fef1adfecc7e07ecb298fd67f], \ + [0x2130a3a7b3221222be34cc53a42d7733666f9ddf714ed7c5885cbbdb63108c21, 0x2df9ee294edf99e3d8d5883fe0566c24aa66731f34a93280e1d328e67b33c9fa, 0x1bf7d6e489ad8c0cf26eb68cc21ff54158132396dc250aeba4b6fc5fc3372762, 0x0c602fa155be958761eaf739617ab136cf7b807728bf7fe35d4778d311780e54, 0x2e50e2c5b36aa20532407d86b8d22d7d5154080a24972faeb63faf0121ed7f21], \ + [0x17c2510982a7b5825710d6290ec4f782f674995ee8409b42b459123b180332e1, 0x0b0d52f03c8af7276803ecf2465b885b21337b538eabd2f6b2ab255f376b42a8, 0x0f5633df1972b9455953d88a63f80647a9ac77c6c0f85d4561972dd8fab8bd14, 0x0ebf7ad29ca13804e1422e939681155124780ff43e76e929035498130a7f1572, 0x1aff13c81bda47e80b02962173bba343e18f94bee27c8a57661b1103a720ffe2], \ + [0x210449dbf5cf3061da2465be85505862d3f31de1a3b58ff35713be57efac6c07, 0x088230c2794e50c57d75cd6d3c7b9dbe19d1e2f1d3001044b93ad1c3ee629817, 0x1c408c256490b0a1da08dc464138dfc78cce9a9e16c7705617a4d6dbb20e7e3a, 0x074517e081eb4c1f22d1771200fb07658f7c77654d58440490dd6f557e9e3903, 0x02d04e9c21df1dbd88524bdb203691b4cee5530559d6cf0fa05adf61e12fdcbf], \ + [0x2eb7a011b8bce91082e13ebd75de3b58eb9b4650dae9f11aa81db32cf1b67b13, 0x2efda77ed35f4af0299f75d6e8a849b54d2ac6bf95368304e6030c18f0cf17b5, 0x09199dcafd50ce642eddbeda65206d4f61a73d10852b8114c51b2440192ae064, 0x268c5cfc446d399c4dd319db666a75b5cb655d8c1797e9fa76181cb4216e1562, 0x2303a652c949071826b0e9a36c80578697b44e912cce6687012854eda11a18dc], \ + [0x27c53563b12a6ee2c3f041f31dc45922bc5353eb110868d237073f4efb35fbdf, 0x1201a87eaf4ae618f02bd82d0a5109049969b5248cfe90f42c278f22615d2b0e, 0x2c43169439fcd69ead8214997bb069becafcb1ba2c51e5706cb4b43dab2a443d, 0x0683597315359040ea03c45d6984c6894f46cbb36d702e3c4fb9847e6304d944, 0x03545706706eab36afb93b128febd16fb0425e158314197b77795ad3a798d183], \ + [0x1a33c254ec117619d35f1fc051b31728740bed23a6a37870edb393b71a0c0e6b, 0x1ffe6968a4470cd567b0c002281caf996e88f71e759b87e6f338e517f1690c78, 0x0fd66e03ba8808ffecb059c899fd80f4140ddd5d2a5c4483107f4e02e355b393, 0x263ab69f13b966f8197394552906b17e6c8617a7bdd5d74a7be3396b7fe013ab, 0x16a425e47d1110625054d5a165de413e3bd87d5aa3958fdd6eb7e03e39ba4046], \ + [0x2dc510a4719ec10cad752f03c673f0e253cc31d13e39e909fcc5f73af9138d9a, 0x24df8e8d856c5b5e1bd1cad23d07dda3423c5179329b7a82cb4aa709a94576e5, 0x2bcc94ff4fc3c76f3cd5c68915a042e87628249a01b09561bdf24a6cdce5620f, 0x076c1e88dc540c8d8de54e343df7c429d3295f52c38cffe6b48be86852da97df, 0x09b5f209a451ac431c051fb12d9a5e4fe40ee1601120947da990fb8e12cb46e1], \ + [0x205f17b0d8729e2eaa88d6a44135a6ab64e9424f55b0f1ea0683af75eb677c07, 0x281c5c688836f6cf912638c38be046cd091681f0a41761720cdd1edf9f237029, 0x1a053e6878e900f45f4d67448c471cf3009a44e7a02ea50e4afa44f2592621f5, 0x100dc7d426debe3007fb7ceac84e4f5468efcb897e7bbee981742839d59e064c, 0x17022672a016a957bb87e2cfadc8b75fb28905bdb62c82c80b1cb31b411e49c8], \ + [0x1086db7e2760fc8b71053a87ebe151239fb8b547182b170de0c27203f954f4d2, 0x15384fe39d73b63302460ae4c2942fac2b41fb65a185536fb85dd24fd7584064, 0x2ebb599fe9136d424bf4abc5342c6c7447b1a853205fcfb5519e551357709008, 0x1b4b5e87cfb9262cfec3c0f0542e4c5a4cf278292b4ce3eed996fac6f4d37288, 0x2465053ae50b6885801f3f82e302cafbbb4a7581bb4fba60b637febe659e5057], \ + [0x114f32edcdea09cd095c5bb5d38f1b97da9f05e18b3708bf6e0ab9d3d54859ef, 0x2bc70dfeb2baab2f6b387cd77be779ac2e5e5519f3d18123ee28d8c2543c7148, 0x01c9bf7a203ce22b775e3a61ad7e77b6a78348b9f6ec68a412e49bfe32c05415, 0x0514b0fe5909ea887bedb0295fbbcec355cfb575ff6a97cd9f4ad00ccb57ee9b, 0x267c76ec81934cc81a132a8b058910a12092520b12a201af03e3202d7b6c1b7e], \ + [0x29170e3322b3d8d5c78c84babbb470adf1622493ce83e95cfb151cf757bde5d6, 0x019f6a8124b19e33af33e5d3873f9c335c6f09a45486cab536dd596ca41d9519, 0x1904aa4d6908544a8b348e9db1981c27009ed8ea171518ae5405d036242b60e9, 0x26f17873949bc679f7f043956694e422b3cee1de9dd6f6473b932a476455ff1a, 0x1ac668f612b8243c193b33720b8aa54040c476031197131ebdcac9b18bc48f75], \ + [0x0996d961a75c0d07196dae45bf624766ccfbf8555be9796da52f81568ef0663d, 0x030c97e1b8cad1d4fd50d1b4383fbe6674d171f99c63febb5425b395c24fc819, 0x06e3ad6a46900e2d3953370255b68f89b3e523f1fe502642ee226f2d8bd0848f, 0x1d6b3755331cd0216b6880e42f9880f565cb94b0e0455153a329890588cc916e, 0x28e4dcba4b96f12a59b041535e730ac8c35189dc0b85ac033dd38c08bae531f2], \ + [0x08b6086046a835508ccf484f2974b6a6b0712a476260376c7a3b3e4bc4a47a14, 0x162cd2ca7fe3b5f1444bcec97812019bb6fd85fba6a0536a89643e15b9bb3b52, 0x28f1e03baaea9bbc05af5b11937e4f5cb5c9a9c1192063d1998c01c64d483a76, 0x1bdb062778d7c15da395af2734c25faa0127d2aab4aa71366031a0bb6791ce10, 0x2375839502e09890cb2914e829627e0e0fc98870b2324a8b50329ebdd24749cb], \ + [0x1fa8662fbcb61fb3ad7c55668dc9423a332dc87cfb2df456e92d33611ed7bb50, 0x1e4fad2dd6b0a6f1f8707f721716c8a446e2fb2c47a5138f3f7f9736079d7694, 0x211256d16c7269fd6df6f5fcdd1fa788ba3bd050059f53d261b0f5f13731ffe7, 0x2e49084b336eceaa4f8e2a2e6af08318f42060e574dda341f4a1079b12bcc5a5, 0x0ce19f54cdc39f7f3bf35192ac6808211aecea08dfe14cab758d25891fb00bb9], \ + [0x0011c5d56c390e893cc394221261d8748dc60451e4ae4e1c84a8468bab2c14cb, 0x17d79ff06b63ac2a8a9e05ee6af3dbb7ca60e17bfa39b47514a8cd8051579b4c, 0x19a7d3a446cb5393dc74560093592b06b1a8b35cd6416a2ecab00173639015fa, 0x030c00a0933dcdba2a808b2e1b9282f331f04596d8928da7aa6c3c97237037a6, 0x16bcb447ce2d50f3ae25ad080695382e935d2d00184c4acc9370be8aab64139c], \ + [0x12341b46b0150aa25ea4ec8715312997e62124f37cab7b6d39255b7cd66feb1d, 0x0e86d13917f44050b72a97b2bf610c84002fc28e296d1044dc89212db6a49ff4, 0x08e6eb4089d37d66d357e00b53d7f30d1052a181f8f2eb14d059025b110c7262, 0x2ea123856245f6c84738d15dd1481a0c0415ccb351a1e0cee10c48ce97ca7b18, 0x2dca72b2ebcab8c23446e00330b163104195789025413abf664db0f9c84dfa6f], \ + [0x06ff9ed50d327e8463329f585ec924b3f2f6b4235f036fa4c64a26cbd42b6a6b, 0x246a10b7e3e0089947f7c9bda3d54df8e2a60e0cca84ea2ac630a4535afbf730, 0x22a63501c5f04b9018719ed99d700ee52f846a715ae67ad75c96b39d688b6691, 0x2f4c50477f7fd9c671799ac5d2e224cdb9164f58351d8aa140ec07e514fae937, 0x10ffb7aad1f51c7d13b17f4d876d9a1e38f0ba8a4a23d4b50cda32cad851567e], \ + [0x0e9cefddc3c2d3bea4d39722532d5420784027352187e7af1a056935c35803ae, 0x07af84a4d3141e7ac23352e6dc6ea4afa1656f96a33c8978a3e83bdd4ba62b41, 0x2d9e31a10aebc761f8de00d14b1e566d1a39323d6e89b638e940f3ec8a22c3c5, 0x27f19a6532e66b5333db1afd592f66f1d36034b314dad8447656747be27e64c7, 0x0058fa3c8454d63354b2024c3b4a577a180ed99f8f3155cd7e4d617d47d07ffd], \ + [0x041627b6715b780967957c080699343eb0414a205d3a175d708964956816a5d5, 0x006ac49dd9253edc7f632e57b958ccecd98201471cf1f66589888f12b727c52d, 0x0131adffd8bd7254b1d8c3616bbe3386ec0c9c0d6d25a9a4ec46a6bf18301398, 0x1c4a6f52c9fccf7a4138e413ef62a28377977ad7e25e49a3cf030e1cd8f9f5b6, 0x03f2a6be51ec677f946551b3860ea479fee048ae2078aeb7d1f7958d2c2645f6], \ + [0x2da770aad2c2eb09391a0cb78ef3a9648a1372d8543119564d7376396b8ddc62, 0x15278463665f74cddc1802febfab02cec9d45fe866c359c738062afb75d64a03, 0x12fe278aa36544eac9731027090518d434e38ea966a08a6f8d580638ac54c773, 0x149b9c802182558a4c45d119d3f4cc7fd8587604ca4f0d6e21b06ff30b6a23b6, 0x0812e7b4d847bc8517d19319772f3c9855e044fd60dbac9a0adc4959b691dfe4], \ + [0x02ed8d8ddeafe3d9d8df7f28a0bfaa7f555813c7e7503aea2a66973703a0c61b, 0x0ebd073ba0537b514deb6029f921029e55e5e4d9a03d6b6ba1304038662d4db8, 0x15c754d5b14b2c4205c6ba8d2ccd028255b3e792c6afa08b44ee75b62eff9f59, 0x169515c89ac5479db0ed8fa6fa311b391cc1235270f4cbc5c29e7cbc30e8732a, 0x25479fbfb3a68f982388f2621001101608bdc29f6ff037696d9161f5cd9a4fef], \ + [0x14475c4bd520451f3c852cb0311a578ca7f8e6e972182196ce09486e94be6071, 0x045a691066cc66bec9baf2798833a1dfd3a847502aec8d5f5c4e73363d097799, 0x26029c0c267c799fb833ac8a11e3a3f0147a8ca037221b90013b8bcb37eba683, 0x163facb34ff572fbf7c946969c1c260873ce12a6a94a3e45b8101d5b948d1641, 0x2c714e96e1913b351d969320cc69d5ec13e06a6275e58688af8ee00c4240ee28], \ + [0x1c1661e2a7ce74b75aba84665ecd2bf9ddd6268f06debfe2d52b804eff1d5fa6, 0x06a69ae795ee9bfe5e5af3e6619a47d26635b34c2a0889fea8c3c068b7dc2c71, 0x113d58535d892115c5d28b4c19a3609374dbdbadf54195c731416c85d731d46a, 0x2ab89102e2b8d5e638ff97d761da6042e534f1ff47f7917a2ca1a74063b46101, 0x03c11ca79e41fdfe962730c45e699546349031893da2b4fd39804fd6a15ad1b3], \ + [0x27096c672621403888014ddbbbfc9da1f7f67b4d4cfe846c6adf040faaf2669c, 0x2de32ad15497aef4d504d4deeb53b13c66db790ce486130caa9dc2b57ef5be0d, 0x0dc108f2b0a280d2fd5d341310722a2d28c738dddaec9f3d255754448eefd001, 0x1869f3b763fe8164c96858a1bb9efad5bcdc3eebc409be7c7d34ca50365d832f, 0x022ed3a2d9ff31cbf82559fe6a911843b616945e16a568d48c6d33767129682d], \ + [0x2155d6005210169e3944ed1365bd0e7292fca1f27c19c26610c6aec077d026bc, 0x0de1ba7a562a8f7acae93263f5f1b4bbec0c0556c91af3db3ea5928c8caeae85, 0x05dbb4406024beabcfce5bf46ec7da38126f740bce8d637b6351dfa7da902563, 0x05d4149baac413bed4d8dc8ad778d32c00e789e3fcd72dccc97e5427a368fd5e, 0x01cdf8b452d97c2b9be5046e7397e76ff0b6802fa941c7879212e22172c27b2e], \ + [0x1fc6a71867027f56af8085ff81adce33c4d7c5015eced8c71b0a22279d46c07c, 0x1040bef4c642d0345d4d59a5a7a3a42ba9e185b75306d9c3568e0fda96aaafc2, 0x16b79c3a6bf316e0ff2c91b289334a4d2b21e95676431918a8081475ab8fad0d, 0x20dff1bc30f6db6b434b3a1387e3c8c6a34070e52b601fc13cbe1cdcd59f474e, 0x0212ac2ab7a6eaaec254955030a970f8062dd4171a726a8bdfb7fd8512ae060d], \ + [0x2f29377491474442869a109c9215637cb02dc03134f0044213c8119f6996ae09, 0x0984ca6a5f9185d525ec93c33fea603273be9f3866aa284c5837d9f32d814bfa, 0x0d080a6b6b3b60700d299bd6fa81220de491361c8a6bd19ceb0ee9294b24f028, 0x0e65cd99e84b052f6789530638cb0ad821acc85b6400264dce929ed7c85a4544, 0x2e208875bc7ac1224808f72c716cd05ee30e3d20380ff6a655975da12736920b], \ + [0x2989f3ae477c2fd376a0b0ff3d7dfac1ae2e3b894afd29f64a60d1aa8592bad5, 0x11361ce544e941379222d101e6fac0ce918106a463290a3e3a74c3cea7189459, 0x1e8d014b86cb5a7da539e10c173f6a75d122a822b8fb366c34c8bd05a2061438, 0x173f65adec8deee27ba812ad29558e23a0c2324167ef6c91212ee2c28ee98733, 0x01c36daaf9f01f1bafee8bd0c779ac3e5da5df7ad45499d0991bd695310eddd9], \ + [0x1353acb08c05adb4aa9ab1c485bb85fff277d1a3f2fc89944a6f5741f381e562, 0x2e5abd2537207cad1860e71ea1188ee4009d33deb4f93aeb20f1c87a3b064d34, 0x191d5c5edaef42d3d02eedbb7ab8562513deb4eb34913a13421726ba8f69455c, 0x11d7f8d1f269264282a263fea6d7599d82a04c74c127de9dee7939dd2dcd089e, 0x04218fde366829ed90f79ad5e67997973445cb4cd6bc6f951bad085286cac971], \ + [0x0070772f7cf52453048397ca5f47a202027b73b489301c3227b71c730d76d6dd, 0x038a389baef5d9a7c865b065687a1d9b67681a98cd051634c1dc04dbe3d2b861, 0x09a5eefab8b36a80cda446b2b4b59ccd0f39d00966a50beaf19860789015a6e5, 0x01b588848b8b47c8b969c145109b4b583d9ec99edfacb7489d16212c7584cd8c, 0x0b846e4a390e560f6e1af6dfc3341419545e5abfa323d817fed91e30d42954a6], \ + [0x23a6679c7d9adb660d43a02ddb900040eb1513bc394fc4f985cabfe85ce72fe3, 0x2e0374a699197e343e5caa35f1351e9f4c3402fb7c85ecccf72f31d6fe089254, 0x0752cd899e52dc4d7f7a08af4cde3ff64b8cc0b1176bb9ec37d41913a7a27b48, 0x068f8813127299dac349a2b6d57397a50275142b664b802c99e2873dd7ae55a7, 0x2ba70a102355d549677574167434b3f986872d04a295b5b8b374330f2da202b5], \ + [0x2c467af88748abf6a334d1df03b5521309f9099b825dd289b8609e70a0b50828, 0x05c5f20bef1bd82701009a2b448ae881e3a52c2d1a31957296d29e5763e8f497, 0x0dc6385fdc567be5842a381f6006e2c60cd083a2c649d9f23ac8c9fe61b73871, 0x142d3983f3dc7f7e19d49911b8670fa70378d5b84150d25ed255baa8114b369c, 0x29a01efb2f6aa894fd7e6d98c96a0fa0f36f86a7a99aa35c00fa18c1b2df67bf], \ + [0x0525ffee737d605138c4a5066644ec630ab9e8afc64555b7d2a1af04eb613a76, 0x1e807dca81d79581f076677ca0e822767e164f614910264ef177cf4238301dc8, 0x0385fb3f89c74dc993510816472474d34c0223e0f733a52fdba56082dbd8757c, 0x037640dc1afc0143e1a6298e53cae59fcfabd7016fd6ef1af558f337bab0ea01, 0x1341999a1ed86919f12a6c5260829eee5fd56cf031da8050b7e4c0de896074b4], \ + [0x069eb075866b0af356906d4bafb10ad773afd642efdcc5657b244f65bed8ece7, 0x171c0b81e62136e395b38e8e08b3e646d2726101d3afaa02ea1909a619033696, 0x2c81814c9453f51cb6eb55c311753e84cbbdcb39bfe696f95575107502acced8, 0x29d843c0415d35d9e3b33fadcf274b2ab04b39032adca92ce39b8a86a7c3a604, 0x085d6a1070f3513d8436bccdabb78750d8e15ea5947f2cdaa7669cf3fae7728b], \ + [0x11820363ed541daa10a44ba665bf302cdbf1dd4e6706b02c9e2a5cda412fc394, 0x201935a58f5c57fc02b60d61a83785bddfd3150e05f1df5d105840b751a16317, 0x0a8c2820c56971aae27a952abd33a03d46794eedd686cd8ecfed610e87c02e9a, 0x180638ff301a64ca04abd6d0bd7500b6650b65ff33e6be1fd50dbc163a281877, 0x095c716266f1de59044f97114a4158a3f85ca8a937cfbec63e9b321a812dd36b], \ + [0x17c31ea02fbc378320d86ffed6c7ca1583b618c5c1a687818d4087a497d73490, 0x05b86c4bb8ef318b6a7227e4192d149d3c17a9764ccd660de4d50a77f192a91b, 0x265bc95df4a4c4876ff70d7ea2fde2c7ab15f4a6ae0d237cd6ce74ba986c7a7b, 0x24752b47bc6c6bc8d9bbe48f5fef2f6908701739c5f5b4b3d6c886d4715c7929, 0x14814a1e0f492a4ea0d86e527a96482178d624b98da96ee5e583b9324d974efe], \ + [0x10def931073b6479bd60577378f29381997c8e041d3cfb3dc7523bca906f00bd, 0x14f7ae770bf7e95f7f706c0d8ab4ed03fa0b880d28c69d031b4592c98610175f, 0x1aef50a0cee751b59f926af40e8035d19decc9d428ebe4e775c5cc9dce1ce589, 0x041935607172f68eba65ca60068dfe3b086c2a2d57d09602951214b57e73cf5a, 0x26863e9dd24255d1573bd083959b856c0493fbefe83c819837a151d3bf452cb8], \ + [0x2036efb6f9830965eb3d7a068bd087c9f5adf251ba62052c652738e63ff8b3af, 0x0c712a975b74dc9d766b639a029969ca30be4f75a753f854b00fa4f1b4f4ee9b, 0x08014dab3cd1667e27afc99bfac1e6807afdff6456492ca3375731d387539699, 0x198d07192db4fac2a82a4a79839d6a2b97c4dd4d37b4e8f3b53009f79b34e6a4, 0x29eb1de42a3ad381b23b4131426897a32709b29d53bb946dfd15784d1f63e572]], + "matrix": [[0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, 0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, 0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, 0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, 0x0aaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977], \ + [0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, 0x281154651c921e746315a9934f1b8a1bba9f92ad8ef4b979115b8e2e991ccd7a, 0x28c2be2f8264f95f0b53c732134efa338ccd8fdb9ee2b45fb86a894f7db36c37, 0x21888041e6febd546d427c890b1883bb9b626d8cb4dc18dcc4ec8fa75e530a13, 0x14ddb5fada0171db80195b9592d8cf2be810930e3ea4574a350d65e2cbff4941], \ + [0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, 0x001c1edd62645b73ad931ab80e37bbb267ba312b34140e716d6a3747594d3052, 0x15b98ce93e47bc64ce2f2c96c69663c439c40c603049466fa7f9a4b228bfc32b, 0x12c7e2adfa524e5958f65be2fbac809fcba8458b28e44d9265051de33163cf9c, 0x2efc2b90d688134849018222e7b8922eaf67ce79816ef468531ec2de53bbd167], \ + [0x0c3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, 0x0dec54e6dbf75205fa75ba7992bd34f08b2efe2ecd424a73eda7784320a1a36e, 0x1c482a25a729f5df20225815034b196098364a11f4d988fb7cc75cf32d8136fa, 0x2625ce48a7b39a4252732624e4ab94360812ac2fc9a14a5fb8b607ae9fd8514a, 0x07f017a7ebd56dd086f7cd4fd710c509ed7ef8e300b9a8bb9fb9f28af710251f], \ + [0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595, 0x1049f8210566b51faafb1e9a5d63c0ee701673aed820d9c4403b01feb727a549, 0x02ecac687ef5b4b568002bd9d1b96b4bef357a69e3e86b5561b9299b82d69c8e, 0x2d3a1aea2e6d44466808f88c9ba903d3bdcb6b58ba40441ed4ebcf11bbe1e37b, 0x14074bb14c982c81c9ad171e4f35fe49b39c4a7a72dbb6d9c98d803bfed65e64]] + }, + "zkifbellman": { + "R_F": 8, + "R_P": 60, + "t": 5, + "a": 5, + "round_constants": [[0x5ee52b2f39e240a4006e97a15a7609dce42fa9aa510d11586a56db98fa925158, 0x3e92829ce321755f769c6fd0d51e98262d7747ad553b028dbbe98b5274b9c8e1, 0x7067b2b9b65af0519cef530217d4563543852399c2af1557fcd9eb325b5365e4, 0x725e66aa00e406f247f00002487d092328c526f2f5a3c456004a71cea83845d5, 0x72bf92303a9d433709d29979a296d98f147e8e7b8ed0cb452bd9f9508f6e4711], \ + [0x3d7e5deccc6eb706c315ff02070232127dbe99bc6a4d1b23e967d35205b87694, 0x13558f81fbc15c2793cc349a059d752c712783727e1443c74098cd66fa12b78b, 0x686f2c6d24dfb9cddbbf717708ca6e04a70f0e077766a39d5bc5de5155e6fcb2, 0x582bc59317a001ed75ffe1c225901d67d8d3764a70eb254f810afc895cbf231b, 0x076df166a42eae40f6df9e5908a54f69a77f4c507ea6dd07d671682cbc1a9534], \ + [0x531f360b9640e565d580688ee5d09e2635997037e87129303bf8297459ab2492, 0x30be41b5a9d8af19a5f922794008a263a121837bcbe113d59621ea30beefd075, 0x39f57e4c8a1178d875210f820977f7fcd33812d444f88e471040676e3e591306, 0x3514084b13bc0be636482204d9cddb072ee674c5cb1238890ee6206a3e7bf035, 0x6372b6bc660daf6b04361caff785b46bbe59eb6a34ab93e23d6364e655dc3a36], \ + [0x422af985e648814bec5af62c142828e002d4b014b702760106b0b90c50d11de5, 0x3296e51f12e0f5c49747c1beb050ff320e2eb7422807eb0c157a372dba2ea013, 0x3b76246abaf33b03dd5b589b80a7fac0ae7f1ad8a9623bb7cf7432c90e27358d, 0x0b40e7e02f5cb836c883c7cef72ec48e87c1808f7d829e2ee0bec0ee709f7409, 0x2ee81b5c29c93b8a6e8871c01d0380a698e547475359b4a4befc22ed2232690f], \ + [0x341ff90fc4a8afee9b74c464955ba9b357252e915b8d39ea7c1318eda718f54d, 0x55eddabde058f3b5e9dae90873ec9bd7b05927da36925e7dfb7bc290c1da125e, 0x6b34ad8cec56aae4595c403377cd2aa990a2f09b931f832781221965bb081b1c, 0x707de76df294fb845309d2160e1bdffebefd57a80c8658899e2c95e77254c752, 0x05e9b152bfd4946b9c109f930eb01892f314597507d28c735a266f4277bb2a32], \ + [0x1589a5cbcee13b696b6f0a1dbbabc08394ab00ed5a6ae6435020e9e3e2fc909a, 0x7116a5d027fe73fbc45bfc60fd875c3116fe3a567e830d1d2d38655223dbd7ec, 0x05382ee6ad97381eb3137f5a90ea13298dac6bc7c2204906044fafc01bfe6ae4, 0x0900bcfe5e7c1b7d0aa80c714b7b2a0c1df7473362138a9dc5c552d11c1d0015, 0x0513deb89d2e48fc729440dc08d0256a79cda84d511a04e0d92cce3c7e55a7c2], \ + [0x6bbb5f1736d499fe3fda42ad40a2b124952ac35fe970ebde38c65cc20ad2afc8, 0x5782ac68a8da0ba09f4d17e7e4b46caa4411a27e60be92168ce75bed95453e05, 0x2d83f3324639c5d83a1ffcf6ac693eef98d8ea4877d547c62b304b0a9f4a0c28, 0x16d3a13700ec503e29ca4d0c6342864595134408b6668bbf1766bb48d7f96cba, 0x318050e971e075931253b00430d35f89f40a88fc73d62150882a8e87149d7244], \ + [0x7180760dd839d8bffbf9b1e26826cb4f6de65fa868a8143e1dc8c2b6ac6d1ac2, 0x5cf2aa95907e59c4725cc17c8cf492f9a7eeef2de337ac227a983c444ae0e80e, 0x2b8345763484d7ec02d6ee267b7c737ca9de41e2186416bf91c65eb0cd11c0a4, 0x055aa90aa60ef9b7f3c29c7500c64e6b85929220a6418dfad37ead3928059117, 0x541d5e4be0967bf49a595c1d8290b750305a334f3347c01b57f8ba313170e1ca], \ + [0x05c0a1f16f97f582caaf4338f018f869e8dd0fa32f007bad1a1a4780053d5817, 0x01519e13858591aa93b9c1d7f849276ac1d2011b7fd19a475371c7968d9f52cd, 0x69c30d5a27f4dffa19c956c348287a704676d999f23044036b9e687a45a1a113, 0x58c93b899aa53e06e82b6346e36338841ba7279d2b7a0ecd3aa20f292852936f, 0x06b8a12870a15479d41018fed6f1a29102ae23e13d0fbccec93ace48bdb9dc93], \ + [0x33eda3c347379e61c2297aa1026682d22f95dc3c7e46e68ab3adb4b0939d76e2, 0x187728045111275b93a1218a148ada85a1f6e2059c443ac7d61fe81e3130b89b, 0x397ec485c5a8b0c8a03ff543e9a9e5a4dc0dd4849fe955bb77b452e2e22c4f17, 0x2f33f8de90f81248455d5a6592667092992be0468372addbaff664caa84cd2d5, 0x061a1a458994ddf9f38c5edfbd737d3ceb05deaee685058b14943e7e9246ebca], \ + [0x4b73ab5b9d35f47307b731e3cf1a1a22e7068e2744f2af0ef6bd78bf8aae4845, 0x5578b7ad5f8d4f3b8e618af7d8d5ec8bf837d2d9486527fe2f9bf7464f8516ad, 0x50b4f055d860f89e12883209f847a4b1a2395fb419eb53c182dbb555c962255c, 0x0b2da770936d6c778be289557ddd2ca024b93fa38c5d4541344e883a69611813, 0x47d8441e1ae7cb8ffc52a18c67afff3cf7543cad51605b2d4e2513f1e1868b68], \ + [0x619da3bf44b42acd949ed572c9f3c195ed20b0b91bcd9e95ee3750d26f3b0ebd, 0x6c9e249e89b2b4cf9cd7772950e0cc9d06688d4f051095eafd116371ede49ab7, 0x210bd3217a141c55877d4528a4e80d5d81d78de7addce85994082281a6250d4b, 0x4e1d8e4079c14c83847af6394d7dc23f33ebf71593379583ec574bf5c86ea9a6, 0x699187330fc1d606e8b31b677651a2c7d1c87d4d001018031792cad0ad3f2826], \ + [0x2946bfc0f45c1f1a0dc4c343a85259f6a6237f064481fe66eda76f01998a01ea, 0x5543e07588375c6d800e5e42d1bfd8b7a92a2a35d65b234ded85f879f82a3d66, 0x660e9d0f2f866e8d12b40dd9d9c03cc8b9ca78600bd649f0fffb2c388dcc8b43, 0x38f06c48d4dc53cb1b69619244cc2a610fdc4229ea316980dffe9131a72b4209, 0x5c9a73a16521ddf463f9de314dd5f7255bc66add48297615b761f34e4636762d], \ + [0x310931f0204c9936fe659e9ebbda832c930172130b3f5476c6c6ee5e7fef3e45, 0x72eb1d833664d8989998af11441ac49654c12210b3465e5ac67a99679634a3af, 0x6981346585a2a466a9255841f710e1d083bdcc21c0aa6721745e158218767a94, 0x0370a259836b3766d563ed3cdcf55ace52655111a1017d8c76eaf8f97e81d858, 0x4f63c45a324b8b974c22a20a6c670eb62d47ef900541b63f1d362b8bbe4ec418], \ + [0x6a4c7347121c2d4745ecffaad22281cc4d58ea74453b7d2b625b890190fdc7ad, 0x36d8869bb69a51ee99622af09d6878c5b715084b25f6e4560a7498557fe87fb5, 0x18faa7f51e1b7a442f9123806872094c0de8a46a6d8402f31f0cde3fcb878394, 0x3610d022aacbe58593e0d6aa7eefdca767f5ddfe7fa1fb9fb4f80225d82b617b, 0x3b5f13d6a8bbff31569bc6860087b2a4b361146a04ad5fc7396a3d0c59f68c1c], \ + [0x40e919335051c6aaaee033745c41b6fa36739a097d94ce6eb075ec03da2a978b, 0x2f54586ab9b7886340f8ed5254f29128a85e2fb1e3725bf3c9cd8bddadc947f1, 0x00606231b689a040363e5afc050f9fc9296d6c620a885eeaffe91be387cbe96c, 0x4b55696db6b0fa327527a76e6ab6b688561c879e53d858e4c90a1122210130e1, 0x569c39bd78356991953aef4b1a01fdf71710bb05eea1f447c3e5efe13bd62894], \ + [0x537f73fcaa256497a2582e45105f1dc10f39c7fce9b88cab5523af3f5f82dcd9, 0x2d58d32120c25995cd0754ab9fdf9ad67d67623cfd1fcbf489f51fa6e6eee4a2, 0x37cb0f655951fca18a4ccdddd4d8466f8839ba8e320a104cb47a59cd387d322f, 0x4e29d154430c9bced788d2eed8f3e01b5da24c1d3710e490bc40ee6d5903213c, 0x47597b7a9018192ef22d6dd24555af1c0c51d8a90b54d8a0bdc2df7967d7a28b], \ + [0x4e01b43205fca0b4a32582abe600f3a326035fe7e028cb0569bac43c997b98ce, 0x0172ffdfba7e43ca807d5b5de7727b4e41706c1f2858c1e8a46c27ed3eae5ff2, 0x2216dd907ab98c0d1e720a46ef83334a236d2c134ccf35ef8e889421e70ebe03, 0x168709f668b635f03607a39390a0de71306d6430ce2babf7292d789d25c0f8d5, 0x0ff6a3823440877dfd355dea80595e21115d0dfe3472cec4ad1437572cc6151d], \ + [0x44e37699b3c72f50ec1a754c72e6fa3f5a074181dd63d189ba36447d34e536ff, 0x267298d2e46227f7f7f422e3059f18d83a8795731b13f6568ce54730cd3fe9ae, 0x1ecbe7a60848077203373441a5b09b44693a155fe226442259e37ac47209235a, 0x31cb23e6b5d7393577d5f5c3368c5bdd5b434ee6319f07e502031cc393d4eccb, 0x5d4c550c4a6eccd74b74d6279b3d9bc755084588156a1bef673657dc2116ecfc], \ + [0x226056b5dec9afd19190ac48740c3b5ab1bb429b19f56894a3dec3f104d238c0, 0x09077c021183dd37ad10451ded70d7ae6ec4819ae76ce23fb2a0be63e69907d9, 0x53545c868ba0fbf0ed1ed7a24ec11b2ecfba5b37fd5cee80774e1ecdea991ed4, 0x69521c33d148e678ca10b33103812cd27597c4a6cddbe83f4970d4b96e03304d, 0x01d5779be7477b96aac6532ef919e61c624072be54587e0698999dd5f460e446], \ + [0x57875a44441d2f191ac7d8de42691ab55fd3401bbaf04b786ef0603b3edf2927, 0x1d5c957da0832d5b94e76f7abdb190972774b594ed232810bfcafe5441839d37, 0x1b678335a80fd045fc7ce1897aa129f67bd55ca9ca801bd88eb7cc868538bd7a, 0x31e69d706a5c1e011c1cb1809e5bf1857c90f9f50b9e1ae5ad36e4d3dcdbb7ed, 0x485df8462ed7a18de34aa6e99ecc9bbf2db075a096b56bc2943b76a99c4bb1a0], \ + [0x1e46fdcbb3705f663a350e78f99024912d80c95779195807aae82cbb494ce9e4, 0x441d0fa0e9cb86c3a2a1f87151681c603c3e028f1a0670be2149eed4f0a24f08, 0x02a3caff274f40942062340ec1fae17c1b1e97c2f0fc7e847c90e9317fea2c0c, 0x4caf281080c0b2f2f638bf0f4859442f4c9da94e9994dada34c5c914130c1a9e, 0x444470c6c49b5b9a38181c3af20bcfea572450946135baea85cfd6b692fa6464], \ + [0x6d5e07a13376fc883bea2dcdbad7f80b7780f231cdd33f5b98618f42cc49ec2f, 0x1b9470418a07d8c88c767d1e63e8d5cc7f810cc530db1340181ecbbb212e0f70, 0x4134c8666c685b712f4aec72077c540ef4a041dcaa123caabd57b83fc6266f14, 0x3d5d0489e27362db9bf0cc7217477d81d2a73e1a44edc43e32d43bb544287c9d, 0x71d7d4a91945e796f538f03b9324497489009ec1a0a403de062ed5bb4d7c2400], \ + [0x646c3d732a94f722384ac266b41e06cf21bf24fb9426c9556d8ac9514f0875f7, 0x4f860c9e5d9bb73057d93c207902d9e60fd6a7c779fde1ebf16b853dba1ea9ad, 0x05801566eb9e119e2f9ace565c9488cd999d66a5753eb4b9887363137baa09ab, 0x0263bdb8654cf1245ae4589370dfd5eeb109a50944eef54308566055b887ee01, 0x4cc39561e65eb05cb8c83f9854750a9114a996eb23e6a0bb07d2d61f0baf0a62], \ + [0x36b544778b2fdb94f808ad8d077b7f0b44f3bba515ecdf026919e2fed09a106d, 0x3fb1f7aec47cbe990151d4bf703c38349b95f409abdf0504e67c1a55ef82294c, 0x637e7eb19cf539aada7e48bc6b72e5ccb0e3f6913f18a0d55696dddfcb1b587a, 0x73bc630fcece6947fb81ac8e0f1f1671ed6042c3ef3bbb12ed554f28b48b46ec, 0x304b46f52d597b964fbec3fc0dceee442febe6131359e156c194ab7be2a11e6d], \ + [0x067d85956dcfff7fd9f6a0fec505b7f4998e3d85672623677a6d974d6b111de6, 0x65830d8053bf8afc0ba5274f1a4c4cce617fa624b480f13ed3eb369fbba78e67, 0x6c32c101e08a962bd996d759a6c012a4d97aedaab9fc99c1fa735a16cd24dd44, 0x11fb2d160e41a1845fd14578c617285081fb1a16a21b36cfd5065b30fac574e3, 0x50aada39348c4736f6c59f7f053c488ed999a33ad23501d9c635aa03baf90db5], \ + [0x5a5f0e3a32b260fbdfdc8c0eaf3a99396992b50b6dbb63a9d1e1ddf9c91d78d4, 0x62c9f6d9aea355d358f2986ad487c2ae443122e1edfb076930865608d05c3b39, 0x520cea06cee20150703a1c8000d4a5f22b3efeb9e34eb90bad0b4ff091b33683, 0x6da4e4682545c1f4c0076f5845fbbcf48632a9c193a92593d12d248031f2c893, 0x1ba5502cee2ea2d07a64f68f0a7492d2426382a5b9662d0410e086107399989b], \ + [0x6ab843ca92240f8a82862da071d53f048272d55425907fc8d0e60dcccd5a1ea4, 0x3f65c2dfa6bb39c1b291c40f810cc912015384a2a24fd322b6375e27bd069322, 0x6a2df71a64cb0d9a548e3b65ba4e646ff5e519cab564b5f77b3fe08e038b9c3a, 0x64776bf2b66bcd09c8661ee6ca6b8251bb4aba5a7ba181464d905db561ca45e1, 0x6d7bed0d258b518eda13368f00be2cc0a94d71cc203d5905c35b10a3ee53eea8], \ + [0x371b958b5c79c889d1786edfe404119773f728822637fb4890b8847a93f97af1, 0x56923182c33cb4dbf0988ba2314378dfd7491b3467b6134e6283c87a1478cbb8, 0x3c4304994ef664d6aa19e3db492c306534281b5b6f857fa6ffae67bdba99c09e, 0x0d003bd3068fa94c4f7bbe6ba02993acd341a27ed2fd7ecaa4e6b0b9d0abd85a, 0x1073cb8c08510e7d88ed4cdf78e96b297cabe9d6677db47289b056c2a640da01], \ + [0x5c57522580fbc75883658d4b7b8ea07e1a4fc75f453c09edd9d249ff1bd31ae0, 0x2a5bec9b422b4dc64958f4752d0c091ffa7904e0ce4809728d16235bb41d707f, 0x379c4a9b4174c5878f72b60fa985f7aa86c1fd868683bdbe8fae194cda2e56c7, 0x3634e042e79d046adb911d57b338e78f51ac7d212c5a5c6dc4fa1a05ddb58c82, 0x3ace976310c5040e1484d1a6d42993ac5923d474ce5497a3fac468af25843a01], \ + [0x3f5a856ab863b7584bc2e6e4c610b9df55a9306eb68894d630ff7d04f243e6f5, 0x0d52822f5581fe9c5dab0b1f8d04eae183deb87c89504544a3d5558594b3149b, 0x3c119e173586c22059bb09d2af4fc1044c8fc44f709233f7625e5fffa6696596, 0x3e154fd5a026d7c6584faf8c089d82fd560f138392a8d4a5fe287859994c96b5, 0x47251339c44d737b21df0ed1e204a28b68c9abb58f1cf2232f8a2da433e24b0b], \ + [0x73d84625f38db2f3842d7724d8e79d6d0349a93b8d6142603eea382ba6ed8692, 0x42929bffc19bf9cd1c53d10440b0760a3be6442db20458b692b4ba3901e6003f, 0x39b16b0fc3700aa93e0cac53fcaf7e84495ac3b49553b2e1a5ff9f73fe74de50, 0x2b715e21640cfb6f77b91a4f6d3dcaef9b5faa7c0bfe94c8d80b0824292603bc, 0x306bef0c637b5d7c8d6486915f6623f4e1ed81971f40772ec60feb5e243d32a0], \ + [0x5287d6ece65ef5df6e1c65dddf1d97cfa019157a5c90c004527c9d7c7496d814, 0x0d760a2132c9092b0c8c89cbdf4fb1bd282791ef6284b73a44b313e8118e7d0c, 0x5e830f4484268a349e4d9f6178ef745460f1f8456b04d0dc7814844052d51eb5, 0x2468669481610965d8439f60a66aa61fbc7b18e82b35aa4755873ec4db82174e, 0x23b6ea9e4d1fde701c719c2afab1272ea22b172bf7afe0837364ad9a2f698bd4], \ + [0x412024b2e86e9d5e903a5fbda26200be47003e3b0dcc322480d3079850606cc0, 0x1f64c17825c1ce9333d211d45a555b5ceaa4608a354ed3237db56225b3a9459b, 0x0b66fa87587ab95d5d29dde50cd606a1bc2c45fd223c03d0693c88b13ae23039, 0x3086c386026698e733e54e5e17f65cb26c17fe64e76f85902cc184d5dd8ef0cf, 0x72036acd9ef575414d5437327d902da6396cc70c0bcffcef2a82b4c296b5ea93], \ + [0x53d89e4470b3ea1eb861717e47c08fda42f6e61fc08118b16645ae5e8fdd664f, 0x4ebea65d1fc5c5167b1412ffcbf8900a8df2096c25d7011e6c74f500662465f8, 0x5ee6e1e0312e78e2e67b246a95afdd79e2e7a5b9b0ef6ee36c3d1639f9736e65, 0x1d770c0cc2c2231213624d58b7875b1715554f6100784bb2b545e405c7fcb94e, 0x2ea5c9837af445988c480fc6a55b1e5640dbe38d5e8cf1ddd85bc42c3658d9ca], \ + [0x6fb78d12c35235f738b1667749064d0066fa7cfe3a9624cb0944f16d37bc485e, 0x35b75e89e794282cee1e66991ccfb2499dce4366b88d7be5f7b5775c12103a22, 0x50e83b08162e7ccfe2d0f19aea4753ba83ef5c40572d6e904cfe2419ee9d901d, 0x3fc5c93031cbcecf12d5831aaa6b2b3071657cd669f7b377b2fef4a7bfc9adf2, 0x37895bdfe29a174b98cd4b49104e56ea09e41c7b50f9aa95b400b529c545f5b4], \ + [0x695e405509a0981035ba77e27cdcf53f3bc15d20fe4e43a335aeb6406ae1837d, 0x104985a48aa7e0a668d8cc7140c255ed1b8482ac5febbd3d7a1cca0e96cf0682, 0x118220b30330f1954e7d94d40fb1043a1a79ca83e68e9ef590601a86a4a917a4, 0x098b3be7845a63543c13d211efac076b94a9528d34cb355faf0ff7a0d5ee9991, 0x69ca1313dcddd8c2f5c5c7ee93a1d2a94726c0c0bc4a303fcf83109b23bf3621], \ + [0x570c1bd286b258b8bf11e8b85a2eb0c6dbfc2e4cdf01a0cde5464aa009b5bd43, 0x4f2921de3696018e0d1ca7cdd5a4064ebf51845ab25b2d395b71c341ea8527da, 0x19035c69cbaf0e0e7e02c5c524a8cc56de0e52d1936a9a10b7580f0c0555878f, 0x2b8fdad2064a6f58d01e8c48d49bb25730780055829c1faead0430afcfbc5669, 0x60ef9a74bbf8b98cb8248856492257f30c7520b3353a6fec9d90d48be46070ba], \ + [0x4c9a6bc8284e783afd6c425f8cbdab82c0db3eac060a2dc00eca48ed6d1d052b, 0x68e6d3a83ac8e60c92d2860ff7557e1fbe3b91c38fabbde8b28371dccce2a10b, 0x56e0e39848046f0305d268b28aa753a41d48586e8579d5f95f12dba60e181d4c, 0x5176824fd8c92fed23df24c382a9fdf86aeeecab0b6716bef53da57bd3f551eb, 0x3aaf796b71041e8b2b494bca3b030f56a0c5663149093c8a179c0f3e24d0f718], \ + [0x101cd65865abc573f5382df3636f4d60bc669aaa70f09ba040d61ef8d09c5296, 0x2581f83d616d932b438bfe0062082d4e1ed7d34b9a1cf63580199731d44a4b25, 0x65d74f6d1320dd1dc9412547b130bc7ad03c4e80cd8a44c108f24ec7aa35489a, 0x0d5cb6e19c9aac7d9f51f176ed42d008317a189dc4f6fc5c36fc6d451a035916, 0x0e367d17423501e62db9fd487f72076f2d1de6dabd3c175341ce35f925c9941e], \ + [0x3f3f101f7c8abd6bebe6b81dadf0ff5fa31ec7140e317909a8d2f94ce4adc890, 0x6d5f212b5f4775095ab1d20fffd41dd73ab69b4ac60e9de11693f8e6bab88e67, 0x6b11154212e86e185a4cb17dc2b9dc061f72bf9cc3df5f95f7b87f1101d09f1c, 0x43f4cf980ff1a9101ca3c4601814f8de4124d108be2584ee9ffb9505188d35fd, 0x5d9be9303e3a25e8fa1abb6f2a7e3250231091100f9d7311b050b52666ec8f02], \ + [0x1eb3b147885e1261d9034ca89a658817caef5ae629e1265cd32c6ef89ce704e9, 0x1595d95dac2c4653d32b01c3fbc294b2922140e41b93c5e7f5702212226d7140, 0x578b22f1f6d6eeb61507f0de1c817bb876b9cd079a18be9e99e2faa8e02618e2, 0x4de38f88c5e8ba1890b3695c912ccacd63721298c9ba3d3668b44f2a13b40abd, 0x0b9df0b81af072be21be9f08df336d3babe6ed5bfc199c73f2e97ccc73de80ae], \ + [0x2a1a8c6d54abda22954e90386d40cc7d5c4f54c592ec2c69a9574601e88b6559, 0x5c5d96136cd1c4ae8fa1db9273083567345b407eb66f73a313ab8ad1a76cb157, 0x1ade9e2b734e937fc2fa04ca445236faf24e6d47ad1a4baa3408102c0d1e6363, 0x49354c394824998704e44eeb2ba6cb6fb431c334b648e6c87565e5fe133e8079, 0x4ea258f019a8055902a696b85547652519b8d8d92de4bf18e2dbfa41264a9a6e], \ + [0x008a5162adf5ebd8711fd8139418509e472abc02908084f2e494086232336808, 0x6badee92872dcc00812a1cbc8081dd65ece0c7d3512af5a9df5fed7428557c81, 0x324c64ef2693e966965246bb7bb8c04b57a21fbee9be8c4a10096222bc83cc51, 0x3f14138eee87c93b0fbfe7efdcfa906525b0ce0f3b9a7431a492f8cb71514219, 0x0db99fa5ce25d50f557415ad181f1399840574f678b2534cae8f774bc8703009], \ + [0x23d984702589f3275211041a4bde9d79329967723ec029da095bdbe733e97381, 0x6c5144ace155e976e287f1b95951194895bac2e5d54b07b62c3afe0eeafcbe39, 0x57a3e420fe7e0638bfb4d0b2c6286c2946166a6eb17836571909da153c3204de, 0x156621c4691a9240863577f10e29dc66a37d1b94e756869984c22d9f9d284726, 0x1b1e774a7ec903650adffe34f6aa8201d356e41e0951d38fb83a89413d078e4b], \ + [0x514b940e5717c1ae53ea29b9a5a15998e294f69c1f553fe56124f66a16a78d53, 0x16350c6898d04d355d966c1d7827eee076a1ebd90781639e120feab665391ea9, 0x5b8b30d8c5ae46c4171d40478886c71c28fc86a3ae4a52ad1c05d8bcb9991b52, 0x5226cdc8a40c229ea4fb08f2c10e0e24cd41f24ca5fa5b5ab73e7340f632e727, 0x64383db664537c84a0a4030c3318f2f19cbeda46c70460035ad9d9240011639d], \ + [0x61068a086ab73c87701b2642af25f6a430240936ba473a9a258cbf90db275277, 0x5bf320a3e8a48c6a85e2dffc4740d1b381ec4aa0771d885dc16adee569403ad3, 0x2603e0fd03264a856c1a7b8f1c5a22c3b98f4858c345e8e0a68e3f6424dd2dfb, 0x100d221342e64ed7e4f1520be70f5b0134031f8a31b4790ebb8e0a89e50b42e2, 0x0e61bad85ce909438ecc028b55085ec2cee0dd3ac5a7bcaa79d96186747a4606], \ + [0x570a2045ca0fa7288d7f372f36bd075c2517a9743c9baa46503c4396e1f316f4, 0x1a64e108621e134020ea761d8f2c5bb42f24fab7641b095f1d164d1fc7b8be90, 0x097f0f28fd299e3597ffd761e9ae8b0fa46526c9d78503dc9dd5f61df3a085d7, 0x1d1063cb1be0f9f96aca5e5e39be9df69c96ff717c7d0c7cfe179cd6dce27505, 0x3e30f5d48b3c2475b8f3ba08cba27caed32b1cf67f76ba9223803733e13ad863], \ + [0x2b30db4198cd832506017fa26430d204476113cc791ee110cf5586af5ce3824c, 0x2b520e374519be203c022ec51dcf8d972dd01abfaea371de9b1532647fca7bfd, 0x183b9a8e45fd480e822f8a97a8d2f127d0ef561914903229fbc5602bea46cb37, 0x4e01e6edf11ef4c94fe8589f9622a70709330a12e68591f6ea7dda994117bdc8, 0x52ee256fb3031d20fc299de7fabd0d4ef2e7f12539760dafb0fbc8560a40ee16], \ + [0x327f5e141e4758d3d9a94c1628a57c817cf84fc0082b8dc098adbe84c1430979, 0x3d0e12036899e5be167de13913901831a714ea5617b94de6de070ddc117bac71, 0x1d9466d50efd1be3080d0aec4b81dd5cdf1ad4681e3ac04d08057f8fe49cdf0b, 0x2360abd7728da2dcda3f495a9a4f0f2aaff1d2420b8f6a7fed6592e1463f3d00, 0x23c1df4ddd6da863a1a2837e5222150278adfd4faf2fae7beaf64ed67a30736c], \ + [0x1e98ec3b325a2a11738273f94516a9d56107f33062661e571342bc043764cf77, 0x431de5d108f8f7109df3059abcc16ccbd17e18676ef64f8998498e4a3f331fde, 0x550937f2bf0f1adb53f412d49ffd2886158703c375f87d059461f740d655e3d0, 0x1341fa99aca4bfc0f511dc9a9bc57c1e7aeb41ebb3a9140f5f93af1b3aeeb582, 0x706889448219016f970b32463a87e355b55ce0a34401dbfe4dd19fb3f93dec2e], \ + [0x28d6207e409ab1c6e8e196d9e363040070b6c6fc4685a5482f80ba38cb792dc5, 0x6827087ecdf4e6bc7c396c59de859cbf08f92c361b5174e7f681ba0e72f83aaa, 0x553e112dab620286f6cf2d31325b971a6516dc7776a6e5ef37bcb11d1785299d, 0x40b44f7413d152f0d46460c54e9572fd91174b4b94a3595d709119e49925354c, 0x4d324dd7dfdf2380ef9f6d3c4f4bc4c5f90dbbbf2f1fd923256913f33a45cc09], \ + [0x609b3ae79dcdc8a8379a690394c95805d862bc31068b572ac126bbc082ebf8b7, 0x33973520a1d9fb67048d64a22ad1b75b081d88c135a556dbc1b6a8479f75eaa7, 0x3bcb7630fc45d34b78fd253d0b5275ecfa85ce48125ef7275c3a9205d01b85d8, 0x1287f419048e81322d73bb9333e9b854e4ceac4b993b5342547263a486b42e34, 0x2a2f5a5a689471d5ef46d669e449ccdc1d37256618722f08cc2c7e75d06fc277], \ + [0x38c913fdc729a28b7e354947f2b6449029976d442e349bc1c2acf3b0fa28bc92, 0x421826bc690adac2b1f3637bc5e2333cb5e4bce3f9e8eac1a0a76df32a7ebff7, 0x30ac2452c3a07bb924b6f7ed47cd6581499d532c5f90bf7fbc69556ff3bf6b09, 0x40ce93f92b281e538efbe7cec9a22a9c005eef428dde3cdd46191630f563ba04, 0x4fc3dd6720c87f672f7b6ff129e9b2a3236ec760a71f78aee84925d8e7616e97], \ + [0x3f3ba6f9f12ca6f934f92b17f4f3bd8ec261e5870610557f687bc734eadaa2d4, 0x11d9eedda8d94fcbed859f5787fe20b7d4483cd319d8215530e2e316c89ee635, 0x29981cff92be6c882c89feb59849d014fcd163699b5b4fdafca335552c4581d1, 0x4c4fe2838d175c666c0d3f20d8dfefdcbcdacebca86e013d8ad29b6a0cf6bb79, 0x630428a99469c03f9027d3c601864185d360d920771ea950732cf000b869a09a], \ + [0x46a776fbf1f36d7fdfa7a210cbb2ffa533540068c169e12f127cb14d9b587056, 0x41a775960677e6c5fdf73c2a409b6e5c08e271cbb8c825f598a1801c84fde5ae, 0x3086af931c41d791deb57f7f82dc511e4d349f42b52c3e0080097c4e44373dc8, 0x155516da7a229b61392a39cc10a67112f512203cab706428f5fbbb3a9fd89fbd, 0x41bdb1e32081ac55f42969658f78e308bdf50175b619c3ca8e3bfdf1ca984684], \ + [0x01344d21e02b9c20d0d886a02167cf8502c3614ab909ae2fa7929b12d3e88519, 0x733a3e92f74b793915beab78e87bd88a2227aa5406df54dc9a2c5e80a11f71e5, 0x6a6cc17a31ba2fe1411cdebeb0809bf4ff0069b0d6ac681edf816ef4c59b6f64, 0x0a77e0a85b06c1b152098066bd36933264641627192e3acdbf611bd002918820, 0x3efb107ebed9b44672f679bffec0121fb509d19e97ae1bac3a86384e274c8c94], \ + [0x3c0c4b441b0ea7ffe03c011db9aab4f86ec4849a0c783a3b7af21b05f5654482, 0x28072c7bfa64f6cb97e4341cd18809ef5cd083374fbec26370c2b0ac02dcdafe, 0x1962306e92b3c7295b2f7435ed8f67dda3a15ec6d8b0786d7727d071663ab22b, 0x594dc533611f7f588838f894a26b1cd27432c63f9fbe03ef2d95d9a2d191ae3f, 0x3e287fec491c686222949bc16c2308ade64e3a0a1dccdb25d64f9d5b94ead6e7], \ + [0x2a95d47fb725b3978a7f90e601f2a9ab39074b35594e0bd133f9c5f34d765d42, 0x29c603ecc031a9750a4d826e4abf3874bc76c76cc7ea306b3b9636f9653ff58c, 0x0bbff6ba283aa42f01172bb82a2838e50941227abc3a2a5b1215b9a6d68de07c, 0x73c7ee55aaa453d36ed857353bc227375244a7e554ceeea2018eb9cb39a51e74, 0x3ff41b13d4cb3140ac8426322e88ff6f16895d88e6de3336cc88c693e0d38175], \ + [0x03043688d4c991763362912a460be95b668fe9b1823fe90febfb3ffc7652ab24, 0x33a29a0d56a7a64d36a67da2c691ff3eaf8ec7f0d78b357e7d2254c5b0e28f73, 0x185db562fc75b43ba2710ad5e9114486b3e9712fe4c88f98b333c0c6211ac882, 0x147b89a0cff9083b8952b3ef292c683f75d523f932711c6e1db3f28f5163b1fb, 0x58ebc5d6b50bb1e4fdb4dcdfae1b69027978826f757ee4dc10d34f963f98fb59], \ + [0x1318791367815809badf1f3ed677e50cef92021c65549b2dabaa52c7b424f5a9, 0x5bce78553694ba32f793c8d7f8d09ac63d0d7ada32b888d61b87849f3eda9557, 0x026bebcc38f0b2804ed21f2e2b16af2194375ff2559fbc588a8962caf0b684c0, 0x494bceff689f9885a3998de0eaaa7ac71a04522700f2e067efdbb037c6e53c66, 0x03ebaf5f0602347c4ed2bdb9a86eb955cb5cd5378f7a6f369dccb69792de8bd2], \ + [0x3626d91f9f05334cb32d3a42eed03f7a553a0ed4cada2db08b45b548bd3b3655, 0x63ee9e5c5cd3c83e93757ed93358ff0583d761e595b62f11df27bd4292ffb6e5, 0x705dd80b2db4492c8b9984439b823681c4d9c8dcddcc04b9786a90051513a0e1, 0x2636ac2ac559be8fe509641dbc67e55db47bb051e05ef06301020c9501f110f1, 0x4781b8da302c7764951730e7ac0892de64537d94db2e19b84eec5a2d9539288e], \ + [0x197852b9a62e16779725f35cd8daf52ffbc8cc9c902c16923f2ff8873795ca86, 0x1c3e49f33fd73480b280dba7744cf67e244449048f8fc84f7b6e452b4ede9a35, 0x41d20cdc6a15c07fd9735c89b155412fcbb7bd3cdfc27abaad2a3a8a90e99743, 0x0c3a7aaeb5f65d907944d7aa48c27648be3d0371bd97a9c060e8ef4f573521b8, 0x52ea7c3f75cba07991674295c4e1462108401b9a103736623943d42e4fbe334e], \ + [0x1106537bf3150b442b0992ee517b69707c3042015e938f97a63d5c924e67f677, 0x71de967042516a5b990ef18ae9956fab89f361b950e0639963017c237ee2a0cf, 0x664a4487e02f7bfa07a1db6ab94a0d1ed0f9e74002bde9cfcbb65f6f74dbfca0, 0x1023721fd7285260935b5a347f167ce721dd6ae5004c4debc68066bac8f2c467, 0x2d52fbc95404515f5456c74b65186c860a89dcda8c84bf68fbf715f3d58fe3f2], \ + [0x6d987c9de419fb6e075441fd99606303e765d8696bcfe01a0d11aa0bd47c8601, 0x422016ce4d744029b1440a288d7988e43d0f29d616c47f70322ff87cfbc69301, 0x1f82afe8eb16611abc6600f7dc2a72c8e1d39643c189f3caa1ead08241a896c4, 0x3bb8684cf815ae6d8a789e0e488c6fb2ac46883fe1cfeb8cfa6f3dbca0f954bd, 0x3d5a1a6e571306fac431b098cdb3c4518f5a8fc436535766fe9e1bb8bda95d1d], \ + [0x5e36e175c5d7df42b86285f43b1e4c6bfbaca19f1019073d38d04de0d0647669, 0x2c3b1b86ce90cb3fe74c5c99b20c3314e28e2f07ce8d932030caee4dfe5055f1, 0x0bfba44d41c49044bce730d8af86fe0397fff85ec10288b847868d0e9834f754, 0x0b79924b9e44662369c615cc8d7f36fe4a4b2a79045cee61c413eaf91d82e0c2, 0x048a11ec75eb154b70223a40cc0db9104b13f6a4ca24e7b9707963ee6f9f74ef], \ + [0x6dd58a400d366014e46b0b9785ce9d78516813ed2eb329dc4531bfbd8e80eec0, 0x112844b7c50e7e676b616e72539d5751dec5a063456921b6b16f9e930cc35ebc, 0x217b616b50e729547af8ceef5008d1edf8d90bc9a7f3ce7c9bc71867e1c06471, 0x3f9a0b8402ffa291bccbb46dcd2522dea790b35a8503da46717c63917dcb7b79, 0x42a44fc114c0cad9badf62b911610bdc4b1a0ba9f656f66173a5476e63dfce86], \ + [0x294223972f4c7e9c9ebefebf059eb90f44479956f5337b12a2eb803e313e96cc, 0x448101837874eb1bda92bc8a632cbf8f70a0664bbcf3a196609b14c53ee4dbcb, 0x53a26c6e2b3df0b17faf6a259bc5531d3ae79da59eb8fc5f594e0b886d8d97be, 0x207c7c32631a75fe8e0da895367176d24e32c5573ec91acf235f3c6c307807cd, 0x20f955773b13b160d3575eb2380b466f7d38cb4a0e12a15d43d147645c3944ca]], + "matrix": [[0x354423b163d1078b0dd645be56316e34a9b98e52dcf9f469be44b108be46c107, 0x44778737e8bc1154aca1cd92054a1e5b83808403705f7d54da88bbd1920e1053, 0x5872eefb5ab6b2946556524168a2aebb69afd513a2fff91e50167b1f6e4055e0, 0x43dff85b25129835819bc8c95819f1a34136f6114e900cd3656e1b9e0e13f86a, 0x07803d2ffe72940596803f244ac090a9cf2d3616546520bc360c7eed0b81cbf8], \ + [0x45d6bc4b818e2b9a53e0e2c0a08f70c34167fd8128e05ac800651ddfee0932d1, 0x08317abbb9e5046b22dfb79e64c8184855107c1d95dddd2b63ca10dddea9ff1a, 0x1bb80eba77c5dcffafb55ccba4ae39ac8f94a054f2a0ee3006b362f709d5e470, 0x038e75bdcf8be7fd3a1e844c4de7333531bbd5a8d2c3779627df88e7480e7c5c, 0x2dd797a699e620ea6b31b91ba3fad4a82f40cffb3e8a30c0b7a546ff69a9002b], \ + [0x4b906f9ee339b196e958e3541b555b4b53e540a113b2f1cabba627be16eb5608, 0x605f0c707b82ef287f46431f9241fe4acf0b7ddb151803cbcf1e7bbd27c3e974, 0x100c514bf38f6ff10df1c83bb428397789cfff7bb0b1280f52343861e8c8737e, 0x2d40ce8af8a252f5611701c3d6b1e517161d0549ef27f443570c81fcdfe3706b, 0x3e6418bdf0313f59afc5f40b4450e56881110ea9a0532e8092efb06a12a8b0f1], \ + [0x71788bf7f6c0cebae5627c5629d012d5fba52428d1f25cdaa0a7434e70e014d0, 0x55cc73296f7e7d26d10b9339721d7983ca06145675255025ab00b34342557db7, 0x0f043b29be2def73a6c6ec92168ea4b47bc9f434a5e6b5d48677670a7ca4d285, 0x62ccc9cdfed859a610f103d74ea04dec0f6874a9b36f3b4e9b47fd73368d45b4, 0x55fb349dd6200b34eaba53a67e74f47d08e473da139dc47e44df50a26423d2d1], \ + [0x45bfbe5ed2f4a01c13b15f20bba00ff577b1154a81b3f318a6aff86369a66735, 0x6a008906685587af05dce9ad2c65ea1d42b1ec32609597bd00c01f58443329ef, 0x004feebd0dbdb9b71176a1d43c9eb495e16419382cdf7864e4bce7b37440cd58, 0x09f080180ce23a5aef3a07e60b28ffeb2cf1771aefbc565c2a3059b39ed82f43, 0x2f7126ddc54648ab6d02493dbe9907f29f4ef3967ad8cd609f0d9467e1694607]] + }, + "zkifbulletproofs": { + "R_F": 8, + "R_P": 60, + "t": 5, + "a": 5, + "round_constants": [[0x07dee32d2fef774b872c091f21fd433bdd25fa2473e1ab9aba302e0f2f27779a, 0x0d2cc38b52751899ba1503a9a1052fd15dab8a4f107879b0253cee5a9fb14800, 0x078d24ce2e81b6ceb60642248cb0d0dcf7c0f12a19e0c7626cfd2f02eb92f43d, 0x0b2f69e1d0e178f547a09e8dbc3520ba0bace5fa9d9a6cb5c779d1f3c7aea9f9, 0x0f5379a444403c992f948b1f3bb8650ecdbc72ba890730da99b937746735e28d], \ + [0x0b40e7dee1486f0863b4552257235df6b61f3734a84d3514816e273b98f4870f, 0x05a270180698004c84f87477a61d826546d4aa940f6e913003fef405dcaaa704, 0x07635e53d64b711d72f69c84831eea2979307c6dfcd804ab89d0559ff072c422, 0x00222c5b43d0077c3db42644e3d336d3a33eb338603e3e541e01300da83f54be, 0x07fe4311214be939bfcafc6b7517b6e9462dd367274cd44a17fe6107c378baf6], \ + [0x07700647a1f79d97aa310ba6723555ed710fa3284102de6d88e443b0e878d003, 0x0ad104c957b45d6e651c12429adf5af9ac00780dbf00a36a1d37205753be8f05, 0x02c4c8acc530d959ee7c0d8e7ded98196eb22c4fd53f095342675c421a51f143, 0x03c74cb2fb155ecea5febd6a05a0223a15d88624bd37c83bd6dd570757d0dd63, 0x0c42b2565202cef9a9c8c34dd3a03deb19a4b9df6195a20c902a05863baed4a5], \ + [0x07d833d313cef82136e6ddab024ac6a007adaf3363873c8ca16b0204ffcdca7f, 0x019978412552ae8619b9a8c2ce2018e05ff10edc1792f2cf445bf1b92f44a74c, 0x05533e7f3ce05bfc69d96416de80653e136f20279b67baeeb3cf6526130e74bd, 0x0709aecee2a65e62a0f16afbfafe1ca6aa353ae9a8f919694c000a07a5b03aa8, 0x096c6624b72aac5501816ce6a4661cda2d1c4571ffd8dc01fc465030d6d07961], \ + [0x002db50f182a8853c740d467c6da5c16dc2e337a117a2e08b46c7c0e36a9fb02, 0x0ec58760d91e276a5fbe9e3fd2cd0e71500fe0f713af7338849fd6e1e7b3dcba, 0x01aa20d70af08a11bddcccfd7530632c87e1929895a1f1734a515fd8cfcbc9dd, 0x0854c77cf0caad23e1edd2d6a6453b85e37f94d351589d8e5361a9aaa466b7fd, 0x093c6f02c4f2fd229d96c86205600dc3afdbbaf81c889c35af51fa9563c7fc2f], \ + [0x0ef3dafb67d1bbf0e8b2217b7dd51dd9ce7e6f990bfe7f339de5e12691c68302, 0x0a4cb16ffb2f0d580a043b47edf46439be91f4bfdafb50cf8295f459d12268f9, 0x092a80f59daedb3a836cb8be0662f19cf2a3169ffdb84b897e6521979451342b, 0x0bcac584e2741298dfb1f7db74f5a00e0f1eeb2a6903dbde22e7557ab5f8a8dc, 0x017d71419f3a54282ce1d0d05ee640ae8e0f47cecd7d0e4686f06bfc88c2669e], \ + [0x01800479969acb77d59bf0f293931c1ae41013846e682babf97b8867b768d1fb, 0x042cce10b92d6af45eacdfb34f342dff6d897deb1416c2d023764d8ce531cdca, 0x0ee7e3e7cd0015aceb63100562f444afd9baae1f18f20c59dce99880f5c7bb55, 0x08d227e5ca3c372be5e27321124b33dae4394680bc7a192aadb83908dc690ee2, 0x043e23a20acd784128472b2c874d573d38f164fddb9fa8fdb2e45ab8df994596], \ + [0x09a676cba3aea403792b4394aaa066d5221c4a506be0fb4605b2261d91a3f5ee, 0x0905a8678f68e7fbaa8fe56f72fe5c812b81e774b5f8a15962900e92214c076a, 0x0969a3ebd43f96dc8fbc0915a2ac6c0bf13f55d95b7cd6830c747d2eb49ce7a2, 0x0028a0f534ab8dddb4f0d88b0e1f94ac6a4cc64d873660ebbafb80a93de705ff, 0x05ca021b7c2caec2c4325933fe1feb766cce5022f40b257c57ad7864552e9755], \ + [0x0178320e9e67004368b8da68c1eb917262ad33570e2060f523d3266794236652, 0x0b4a6b36c7469c0b70e8649c8a13df10120e71164ecfe9939b81580bd57e7e26, 0x01c9714605e42264b0c5b54e27332d43948413cb6ef5e0ec9ec09b4a37f74dfe, 0x093ebdc46e70f0867bc7d5232909b548d992e7779069cd55c672deae3f34409f, 0x0ecb5ba80b49752fa7a50c82e3bee5c9d8b592f753bd73f63f44f2757b6453bf], \ + [0x08f941e796b1879ebaa28e5e9793c08c8b8e870a58ae40afa3870433cbeb6ac5, 0x0e408895f93504ae1f6df9da84abe77cf85ce04f2a78682a0c81e47121613bf7, 0x095c0d3a8659fcd2ffce4ac4993110b10434c43d7fa58b25361b83605e9d26b1, 0x0f9b2a1442e45c753243c25792ac7431e94451bd3b75fe8061ddf5fb199504bb, 0x026203f4d1c5c3ac00eb14158568514b143283d393341e8f5f1251bde28afd24], \ + [0x076674756dd526852df996d00a6da712383ffbb9dfcf04d08d52b51c56603f0c, 0x0a396cf4c38dc66b14213287c680ad59ce5311a81e33ed83d49dd559b2380cae, 0x0c894145b04aba62fd4a1438ffa514320d1604ea2cb4e6280601d8e8845467a5, 0x0e08884778ae5b6effcea1530f35ef973983f3fe589462c1dc4ffa95bca1e788, 0x03e0d318ca30191196014f2398da8ada0b1fb39246bc561f7d79b4b93274b2f8], \ + [0x0b024df08778101dfeca6850bb42ac398847208e207bed1e7ed959565aa78ea3, 0x0f758166c17047aa4c8db957c90557f198cd5b9212e95e04d8ea9d0667d89182, 0x0677b111c96e6e50f9aed5093e61a7e4cd1c00c124abca3983a01b5789eb84bb, 0x076a9e9eb29a01cf7105676455286690aedb5d4c363ba939108e9a0763b8dd99, 0x0537a946e7f4a95fd090486ee233c03c52be02d35464ca7164477c0f94bbde05], \ + [0x0c13198697f71c3955b84097321d8b3f9510327dc968da1017e80a6003c99b15, 0x00560c5e7509074876f1fe48d8055176ad3f6358a7c25dd8645ac8dfa5f015a4, 0x0a1d0df544469b69cecd16303a42bc31e32ac9dc76125e467416d77fcabfc1c4, 0x0c3a9255ac9875c1ad129906e3cbbdafda21fa6e6e3bf578beb3a0b3ed0ce53f, 0x03276f0e69887a7d6eed98b82d96d3d2bc8ccdbb15b75185aab0686d687203d6], \ + [0x02367bef00a9c64f32a56d0d1c20088d0a50485459c1c7fd2b2deafb06a4aacd, 0x086aa6e3baafc0738fafdb5a16d9b0fdc23a1c256113f5d1c6f9d48a50c46bff, 0x0ddc1f4fbbd1bd1ab6655706e3850fb9f8def0c837c5017a80c1251707f47713, 0x0e17668bef6f94c7dfb8b7b256a6477371bc19ce78b33b0851f0e4df5abb3c91, 0x0ba4b91870aa7d4e915e826c5c67a709f9cda2f53e708f243323e9ea7e815d92], \ + [0x0c28d013b8e96dfa88b80b18c3f8973476a938971b785995c5cc64bbd1546a64, 0x0a7387fd12c7b3ac2a602fcb11cfe5d5e78df7d4e0e9454003a2437443d99262, 0x06ea1538310b0f8acde9118db99e0c6d8fdd31009f4cad64695e90d4ad77038a, 0x02cf0a2aa8a6688304faa22507a641bb02fbeaea231e2e75f98b62886cca57bf, 0x006daf8215b541f0bdc434803a7d8072decea01809b317827323e949d7b5205c], \ + [0x06d0de6e11e4c3d429ded0b93fdfae124d2348efae4f43af5fa0dc9d363a3ab7, 0x0f8c1da28d8cba955ff0acceef3724a30a6ddbbb594a89b718e7d3bda1e40ae2, 0x0f1d75bc9e1b3df109604b314ebdba1ca304b7a3735bf9a65cb122a6b0a5bfbe, 0x07bc867f70911d1d63d204e79ac4b8bf66854746262f59a208537c10d3679740, 0x0a514c676d01d22aa1abf800aeda6f999bc07cc5f0cda5612ea6fa594ecd4e62], \ + [0x0d2801727525684c3da45d5f65dbb19cc1522f54c5681c6704c803bb780be21b, 0x024ddeeea8ce986e0c4dbddf3e6d71bac1111f5b9779c427f0b8b0a95a4f3766, 0x0dfba356033d74b0f2ff70d7d20de3943e4e8763cff14175eb9f583d4c95a9ee, 0x0151f1de9cf20404032b62a4f6483c5b2c5b39faadcb434080e56789a866ac99, 0x098afb5fbb1f2b841abe94a2c7fae5a2b283502d9c65b84b0d35af41e4061dfd], \ + [0x0417c5d0a513cb403037a5e310baba24017766be0f242f835b0860fe43cee816, 0x0305000216399804c1688d0f040d67f3c310191323a93a7a53d95a53eb83d227, 0x0f6858b843c969f67f516daf43f628ee04fefb1435dfb6d45ab1c9c924b12b91, 0x0fa543b4dc9e6829bf358925c4cbe7ed82a48da5c8d0aaf53f8b500237019e92, 0x07308272f79608055ab64aaf182baa4c07b30fdd33354c5c405a9e5dd24eec3f], \ + [0x059f6f68937aabe785ba92071af485b72d94b06eddffc16a8f6bf6ccec1fd387, 0x03eb669030a02d9869a77b5840e78972065f2fd3db908a97b11e7840b1188563, 0x023fcbb6c3acf673a35eed022ada71bab2f376eec82416df81c3508c2cd2112b, 0x05648595297a65516c948663d4e50b89480f0547f634f31c6ca3c1dcffe00b48, 0x06bc506ec5d1835a4ae37a68c1c011267bdb4c0286cb7179cabb799f31acf61e], \ + [0x0e3ec7cb37e29c8e78de71fe2b05eeff1d99840207c31312324643f12b1c9eb1, 0x0a2f62b408dbc23b79ca1fd35431ee7bf4141200d086a925eb9b69c359769571, 0x00b61128c313de60a2c80de7795440878ce99bfb24f5d73a917d4ddc7def27e5, 0x0750d9dba690ccdd6948b30c982ab79724bd1c098c96ef60ffc776afba513e0f, 0x0b9c194c9e32125d75676cf1ef43c9654466f0aaa15d6130f97e40be6392f994], \ + [0x0ebbbf4c9ac750966dd77b581a60cd56ba1fc17edcb10ff92580879486d2d67e, 0x049fd0041587e59889641b8214cad071216cf792aa1dd46227441600bed94905, 0x0f90bc7b8eceddfb9371a22ab10ab975e3d3af26f8d65a278471619f20db0a3e, 0x0a2ae4279466528a669bfe755134dcf9f4ce520df0ae4b40d4ad3708bd9f43a1, 0x056017c5b0b7cad1c34fd9227926f8ee7551b22280cf3b4882db9ebf73fac5fe], \ + [0x00fa0c9787e9ea41e336513c87678284866cd04da5f5dfefc8c8ffe7beca5a15, 0x044a1c91275ef2a9ed5ce9f4f7edac3b6265445c143446e8406bf0e237fb0ff7, 0x006a5f66c64c489e02c0c20e7a4e867d85ece871f880610303306b2abc89a618, 0x06cab1b647e06087d5f0fea5779f73e7f72cad94d92c185fade2e35e0d59a0c5, 0x09cb806c8d4b27ab293f1bb88afa0eba2903b526fbf6552ec6e5492e66d8e77c], \ + [0x0ccb800a3391e0d75ccec586b7f8870015c248f53f0f6b2e2c0718eb7d5b9b7a, 0x0c8d225c964fb7c1e17d4c6ab55f6e8e5cf52dff11c2beb18d25aea6e888f8f2, 0x0733a54722f87482177fac3817e09642fa3c0fedeec864344b90cd3a069c2ad2, 0x0985442f08524b9217e33d171b864e731a7bd7ba37979a320dcb8c0eb2e88bc4, 0x097369f4105d11aeb823b38351540675e703513ec845a4356ed11180c7b6615e], \ + [0x0c9e4849e261c96ca1895fc086981acdb75e73e93f0738127498a32f9fdf6ead, 0x0842ef25779d0f578aa5db89dd3cf9a5af233b1d0ece630cc591f52c188a675b, 0x02c0ad1bbfadf8c0d254ec1f457de4609777b384f4925cbd8763c761f6d6facd, 0x07d2ac9ed583400d7093ca483221092ea4f814a540ea74bc9277041de72fbcf6, 0x007fb31b37332c22b0792ccbf0a6ec6099b3f873534e8039ea83da8fe481d97e], \ + [0x0cd9fcbdcad67144b2eb06041beccab24052836b3b498c2748879ae5c23009ad, 0x0a4e3ebe48799b2783d6076da0684189dcba3232a76dc0d77ac4333fcf2e3c18, 0x05f1f39107ea0da82f6d4c73f95b4bbbf4860e12c3b8fac1a3a575c86218a37d, 0x07ef38030c061948abe5e1b83c812d24cad3c47eba405e98d0480b1c46b0e421, 0x0ea5e24f9b4d392e07e8f11b04c974e7eef92c2b365063e0a1e1a03a91095b1a], \ + [0x001103fa27aaa29fd3fb57141211c73af21458a293edfb49eb543f86b8968b93, 0x00945c4e63df690c3fdd1f2c1d4582764a8e311af62d92034c6edef6abe8bbed, 0x08e027fad54a818cdc1f2c63e8d63755ad4669ebd5b752d2bf46e7d024245029, 0x00a562264ef748a355d7b482c5d5cf383bdcc92f0d0aa70e08e6d5d5672b1d2c, 0x0364508460a3ed5fce207207d4d4be005f880cda77f45fdba81b123027c4a708], \ + [0x0d34b7db472e3c3703bb82d7c31f5c85e943ed667554d2e523d6d68f0daad047, 0x0a4eaf906ee4bb69307c7692fbc4eb6d87844aa17359b299aa460d6f79666320, 0x0b7131ac795daaa7c4a02a6a6c8f5c7e4f3a81bd4d781c396e3625a785858243, 0x0e79962d6f1f1d048f4a891795c01c9a20b521139a398183ba6b47bfb11f9817, 0x0dfc5f393c71b77fc78a7be79bc3f6f499cbf54b3ddd7d4b1868be23a6ba9b50], \ + [0x00075cc47da3ef8be846bdd3d906a8a320b0a491d70d2366d3b1ffdafb3f1c76, 0x09dc91f7ade83f990b2b58c9fcb115322bb7764672a96732c1d0d01af7befac4, 0x073a3d0175c61e0b128c5cd6b7230f6d8224e929b89b06da5ee83e481669c475, 0x0d2d705b69ec62705de79043ad4dfb9494994e7134e31904ff4c6bd027430460, 0x04472cd1dc4505835ea27415aa8540563b707a5638dcd8a7d3ecef03a911d25a], \ + [0x0bb52ade1ed065fbc312cfc4fa403a2162a66adfd5c07eaa10e3f00779a7d0ff, 0x0f908cbcc94f336d5cf159b5b2940fdbd5e824f48c3a6cd5d2a96fca82f22c47, 0x005e4ee714e452ad8cd2880f645dbb610bb15c7cab300a525121e134f5d1d9ea, 0x0a9f49a99091b88d252b6d8c92f633bec217f7e76587757ad69a225d55229aed, 0x0300dcadeca268aa0060060b159c7f37d8be9eaec0c14f38b7a62eb45ac879b8], \ + [0x0b7a882c440fe072d3aa3652736d5229db9b205bddfbbc8d034f96b1ba5268c3, 0x00f462b7440a3cd36f3b8f702eafc1e9a238f978141937cf69ce5d96f07806ca, 0x0684544dc8a7290159fe7e3b759f6da19dd454e5f79a782ed45ef9f1744afdf9, 0x01910a2be20ebebc7962e27e15fd6c000e3073b99b8534ff4d5ec2afee510b4d, 0x03b5df67bcc4e7bc48debf6b343edae547bdd8c71b50bfb7de548c99ab7b6f54], \ + [0x062645e3afe3d20c09cca50d0da8baa278bf2fdcbb8eff3ea9708d605e754bc8, 0x042b7e174fb7fa3942caa3d7fc3f9a93ff5d25db763c71c25d1614623ffa6763, 0x023d507d5abf6e4e161e76ae6b50a6edfa1d3330fe3c4f8651bf627bce561d2f, 0x0e45d5876dea9040f3cc4fd5bb6ebd794f186627fa6a9b7f649169b9172865b4, 0x023edbb74d9b6bfda3d0c921941ec709e96faeee33465f3968577fddcc4f9340], \ + [0x0af5492cb84f28fff9e397a669ab3c833bbc09eee32842dbbd85371eea5877ce, 0x094d670eafdcaa4de492d0cb677a148765a504169063b6d9afb3eea9e6eb0fea, 0x0fd9e11e29b56db25cc09f1b2840fd3659805e63ec51064bda85ae577bbe46ab, 0x0aff2b1b9bf22bdd59e2f5e13715f5e396e999ff1d89c2a1fc7ee56e47fca6e6, 0x08436c47178cf5651c02b7267bfd8a49b84f9261458356d2d9547cc85738886a], \ + [0x03b6e7010602d87209eda88e08d9d213d522ebd3a4ecd3b6ca410b98e86feee9, 0x068ff17336cda654e96b5fb3b63f7864bd22ccec274e603478eb121f73e6296f, 0x00ae6ffc6d1aa09739b2e96804de97b03d230dab5fc881ba04e7a2a63951dc9a, 0x07e993165a77c6583ce36f101fa16a0b951d563731abcbaf896a13ceea584069, 0x0bf56bcbf7b17f0198a839258ba8af88e452897382b6872887a4690176bad76d], \ + [0x027aa67bdbb81227562c8bf65b3fa2fc1da374f8ed639a38f1224f169bfbb7c0, 0x07abbbd6cf60f9da344a2d04a3a703ce5fae547b9a74dab799826d344318c5f3, 0x0da1b35095346959dfb9716eacc2a657cab95a99a7a6c85456ce4b1903cbb46e, 0x06ad124460a52fcf7340e607720127f07aa68d75291490335d7dc67f41b660a7, 0x087c8e8e47cd1056f05c0adead81d5fe3bb0f230b08c6873b4b6ee629aec7675], \ + [0x0bab241b9119f8e8779bdb22f0af3f0e73cdf9418a3e462fe1d70b9622aaacfa, 0x03834ff05b844ec5a05af54830c902305ac64957c021eeadf67b63e6014e7422, 0x0db731648c716e89a8a5b65d426a4a8bcef9c91fcc122ad1707d42f7d20abc2d, 0x0a392c41b3673543ffa4ef8cbcaf9b1789b9389f52c38545eb419961c85796d9, 0x080b6e294e1b2c4b11efe5224024ac2206df51064dc5c30626c9171d1e46d5ba], \ + [0x0bc139ded73baf9c285fa16c5eb628ea877ab5f82933aeba6e3d184d6f110f98, 0x0f32935faa4f028b4c611eefd9e30985900da8e46cffd51e0dbc4e7d17ce7221, 0x014e649a1e9d2164573a6ea629df86c0b63e641cb25bd5d104c5d2fdf4b0b163, 0x0478d0859d1a506a83a9a72723b53253411f2ba66e82fdd62e5bd2a06994331d, 0x077ede39f2191d619b4e5f625ac5d72edd34aad2b19ab92bc37519611bc213f5], \ + [0x074efc8e03da0f4e7ded1c90fb7494fd326096fe20fe9dd55918b34b4d2a7613, 0x057fb9867713debe90bd92b180279e6eed202d595a7dcc85e4d5e203e8251900, 0x0ef1a771bf63157a47fb0f7c79fcd1ebd9c16d797aeead1d77168aed5ef8381a, 0x02b66ebca8475efc6b34694d7c91801a8fad43f922e3cd6145d607c9a564581a, 0x0448a6b9d11e05c5904e16c3b1f80b4a0742c5a8f1a3c14063b686a6e7025f3c], \ + [0x0f6025552752aafb1fb15d3be6ac27206b937654727f7012ed097f3c1c4d4428, 0x0eaea21f69692a5bfb8af978fde458541aee8db4005bfb58ae6aad9141480c37, 0x0bf22682a537b9fc86147370a6c9bf4c5d6ef4ce5baab91221af47778062966a, 0x0e07024a2ba9e1be2107cb4acf3e750ec07b0bef8c68c1a96bc406b5dbc2e300, 0x08426e377a363e9dc8e72d64b7ce8e860b29f4acfb0f437734a465db34a776f0], \ + [0x06dd20f1c81aecb2b52331ee4a2a76e7976adb02399c678ff1a437de16988469, 0x0bbeba5bce6720559099e7feeaf5c336d235ca64aae176efaa3887e26dc1adbb, 0x07fb9affe9feece573bfbf8605f7952d0eb0d18e1d8e16fc700304f5c3c3c53e, 0x0c7b271c8d41de4f839aefd8b1537bf7e7b2a5fdc1cbda3c04f048bfcd602d1a, 0x0f9890600f254dfe1404158f2de8bc124fb390926e6848266a95a21535a85d2f], \ + [0x0607f4587c53b568b5428ece605056272dc4f32b3d7e489547b78ac684dc5ceb, 0x06119e69b1a063d7c348df41014b1ba18366eefc0cf2d6bfdf890c0d0ba2f32a, 0x0b9c7641e18283ea3508f280272347ea656db45cf707041160bb54f9a5f8496d, 0x013398ea778ca97e1a338255dbf83602365d1388c0ccfca4b25f1491bdcd8826, 0x055f4fd5a63b8b44c6ff489e5528ccbac34221c9f00c4bc326888ce251310aa8], \ + [0x0f170e386498c140663181a2c5567b3a47fc4f34191fded780d630f70c364de0, 0x0d9e4eed56e18cbae429649d1fc1945c008deca0afeafd801ebc4f76b00ccba8, 0x00ba2c5d3a2e09bb4d13db4b9b9a697e077e4aa3a65455dd64545fc985a20414, 0x0fa906d804cb6081c1cd097e1e5a6d59959776fe4cc292d9d2498e67291205ba, 0x0d58798f0218ffc36b93232a07d27d4a7a2b6205bb0ed90bcf2e20763cfec26e], \ + [0x075e9d58fab5fc4153445dc4db94348ad403b51d5fafa01c1d8b2572e617542c, 0x08e1f2eb9819d9f32a6001848dfe11d076ea2b93c8245fa4af9ab1baea49b3b9, 0x077ac8dd2cfc3e91049c145ac9ba66ee3f5f51702947926e4cf5987580a6c832, 0x0d0aad3d44a92340046c7c39c4612bd53277585545c633ebe8205c8c5c5e0a60, 0x0435e6e1614ddd2526011c30a9f190e1000f3cf6aa675c5069ae659490bc550b], \ + [0x08522c402baeaaae50763b337af53d9cd45640399f283f8779da67d49932f4c5, 0x0f528c3399b05c8b0e8bb38ccecd9e2629835078590a47e1cf9450a9f28adb3b, 0x06ef6effc8ab5fc3ace9809f6004b19305cb88ac37942ed9854cebf432f8778a, 0x07839dc94c51b55f50aa89e39a9cb8de8365c409f25ab5a7b0413e83236be6dd, 0x032f3b1d2275213872b2eb414886156a464a6bef931586ac441321335834094b], \ + [0x050fff0d4cb7ae1086475ed1dbec6c564bc1aa2ef0933d820d581e959cb47cd9, 0x01ab2b26e38b136e75569e90e69e5bc7325382fb5246e2a845ee891827d45197, 0x02c267af3e8f7c9994594bf495a5c6d2fc169cea9f219bc5067e3373df2b15f5, 0x0aac7da921d48e61fc6380b18392a26ddee38bfae29f587655124a59701ea7be, 0x00af7e4f98bd15420514e6691f939b8c886ebf004532f24c0268e69b9667e2d8], \ + [0x098f396b70aa7a3559c3b9b4e1f06f8a500b11504cb842d0fc914ab1608d4039, 0x0e99d808ad2eeb1f412894b420279b84a95b4dc9554cfd9cc6856bb097210605, 0x07b172adba2bdce5c3e70fe278d0d02f9dbe519de6afba34eb29fbff8a0df4eb, 0x013dedc44297240da55b5ec28b90b0011c9f1db02dcace3f22cbd93fbb31e3fb, 0x010d005ffc7828cc2a96a006fbbc572e935ca0a90d7f95ea88764d707fbb9f9f], \ + [0x04b612bd2d76b08813751b79a113861afec9a773aa7e4c5152ace3d20e169b57, 0x013f6d926053049b0d6bdf58c46b419c5de46354b07edb8469474f746fe6574d, 0x09acd4aa7a334750c27e0a1801499ab9c68af6c5f6f4e1769fd5d1499fca941c, 0x01c48b56ec4574c2dd967383ace046024cb3833417fbc99eb7f93748ec1188e7, 0x002b59bb38b1d1da408d9013d17fa9fd8928bcba3e5d604dc56c062480ccd4ad], \ + [0x055f5ab861d254a8af789c7f76efaffcb39ff8307a76863e05df76439772a192, 0x04432ae08c3c1b1834d655d792a2ef10ae5c6af6788bfa170c1da00b01f0bd77, 0x09430e2decf319ea5f99acb123c7e5eebe7e1f5d78aca1cfc3bda48c97ed25ce, 0x037733aa3c745b9e52fc7b0a45f8c0b94a747c3b26941159fba44016a3b683ee, 0x02a893785610c1052b50b2c11180546cc3aa46dd65fae3fec234c1ec12b654d5], \ + [0x07aa6aadb8a7585cb09939daf790eb430cc8502b3856e85119327607328ceae8, 0x0372a781f41169e7eeb890dee23dd29d653e1f1527ea9ce77b594f752db07cf1, 0x0d29952e3b7331a2fe469ed6bda5a28912c7d549052776e7f219e22522a6437c, 0x0f49884237439117144e3ec4ba66736312c6e076f03850247ff56389eaf003f0, 0x075c0104bf94e26484aed5f4d4d365e96ff0dbb4d32a9d49120882533502d8f1], \ + [0x04ad008b742cc5b93aaaa7f90cde56600bdfd5bcdda421afb3afd751105ad9c1, 0x0154c9d5c631b72f85f316f43a8de05cbf6382f41f0c0c3cc0d9ea0ab9d4dae2, 0x05a16b5e4e000808b4550b6f3192f36e27a9174796f3a04a2455278c0689c2b4, 0x07b32b0ff8fadc9bd93ce20a81e09c4d22e4ab424deb338426588f4ee78179bf, 0x06735777c623002f1583d9b90e92f448a44dd674a37a71973b26df31378e9f9c], \ + [0x0f5c2721cb52a4c913a2fd58c0b626100d78d0cc848ffcf42eee00ab2633b794, 0x06c90cd5642c7debacbafe3408e70dcd5cf96947a133c47e09f3ce8834a8feb4, 0x0e4f789179629175932322e86efac2af0eb5c1fe2c33aaa6507b44e41d129149, 0x09ed38c8b60d4742ee5837a40cc7ef79f10bc53151deb2a47d5ca4de80bd8abd, 0x0a5e5bfb18117162f8c47c9d1635239b26c8402d1d81f92d16eed538c3ec2032], \ + [0x0726f11b44ca7138a5689e1f0d7feda0161c1e15af8f0fe1b13db7d5f9dd7bce, 0x07241b4316a3e170c843974957f085e29d56d1628066234921541305e42a2a29, 0x0a32c7fbe8393a16c597181c33fa1107f5a621a4d3db8da7eef10d092b1852f4, 0x090619ae509fb85805abdbfad8e3bc6da145f5c5190be655b05f6f75b8e4cdc0, 0x00fb88c5007647e916253fe380af85576c3f3eaf08c92986fed33eff9e2943e0], \ + [0x0a28056a9d89f6f559b40be24546b368e30099f7e300ad28bb85ea3387e0d610, 0x063973a906a4d88cb43ca14fd618b89c75d726b37953c42bb5a4cc10703cd82a, 0x07ad41dcffe8422d7febaf87dd6c6096edd0ff2248813e13c2979cd69a374c45, 0x008015f5b446f6411273fe520ec53b28c9b5cadb8d8beb3c8948c8cac0754133, 0x08d929c2b6255113a0995dcd19dbcced65e70e9ac8625c791ea0ebecacc07605], \ + [0x00c6835ab1417f404747ebcc83082a77af1f9ff30630e4271969ca99a06153e4, 0x007da9133eb60a2510a5f44c19db52b30d35cefd957979f1c22a7aa3487e1083, 0x0ac25bc7830dc7d5b0eae6031b156d3d6d97ced92d5bd7bf39625d2d3856b35a, 0x01e297d06f7917c4bc7925e738e68cffd44c4705eaa3570a6224e4417e0ed05e, 0x0081502f723fe6221d9e13e2ad5e347c4c2d3fe1e7bb2e8a1bc59a7706da6a4d], \ + [0x04ff945991bb674966cd3d4430891088a4d9d6b343c08647f453a857ffeff114, 0x0a3c3cf20a36247ee718609aaf839f38b4b0bfa601d1216ee3ba381e5478f36b, 0x0493885c587b9b8da43138ad38bf9447873644819d8a9a1ad5f100453a6b80e2, 0x088f694d1671ba99a8b3dc03e6c463d604e2022c0a0518abdabc4424c583a75a, 0x042d3c9bff8cff7201c9a949e6024dc053060563fe31cd17551820cd71ea32b0], \ + [0x03a9ecdfd97d5b75608e44b60a5515c4130a007d941ca4cb4f547bf8718dac74, 0x0e9a03ce3c31724924d51bb5e7c46f10b029ca0ac077c7042782b1f77c507e8d, 0x08d3d1bbd3e9a15ba31cac262fc6cc1bdde69f57b3f29ab87c7b207002b04e29, 0x02950737b097c9b78f8980a248402465aaa6d56e62893950ffc7f223840bfcb1, 0x004601bbeaf32154c05f84f8825724b4d8bff9b876bbca78947de9ec2fff1f67], \ + [0x034844e3664530a155a2c6c94df8c040711290c1b4aaac13fe1c9ec0ae54c875, 0x01a1b6ad5098bfb89437759d055d4423d5b4e52f565a5ba210b456c87484aafa, 0x058fd89d9c120a70da913f73dd05391f313fda09213c478be3b2557e474a3ce6, 0x0e32949d9a784d3c9bfd713b87b1ab272b6eec9d6f27985e27f08d97ac5c4321, 0x0cdf82fbb25e4532c1dfbfbc12149726e901669794863ed1f67ad53e2a63673f], \ + [0x09f2ac84833db7358721e4615d12bae37dc9ba803dbe2e24757af449b5ba4880, 0x0ee8ef5c95d90f3f481fe88068ea26e97e0d384f82096197125a55e7388b0b21, 0x02f26bf968d6ac684d4f4f9e45bd48941d778afe5f1f27abfe918c010a14e04f, 0x0c39ca690cd73f5e03c9b58604540fe9beb5291ade2ccf695845290069f25dd3, 0x037164d2af0731808119ef5fe41a1406fdb97ecc97a2fd57a4832afe0912c2fb], \ + [0x061a50fa8a14edef5cad096483d4ab01120a1179235a70f15a622bb4c1c15cae, 0x0f723b0587e366833fc62ff6e5a3c00becbb1af7fb4da4fc91cfea2c67fe4ae9, 0x01acac3691de4e678bf9c625a2f4fca84c86a2e2aaa093e8a71329cff78a5c97, 0x074854f5bd09b34a0f88e53b78c5ac4212872aabacd957ffb4d8b5bd591e6723, 0x028b9ef647aeef8e864639f96a430d2ec9b2fe960c80279239b4a5b2b3b5da9f], \ + [0x07085968b1756eaa013a94a50f2dac713d806ecab95a4164f4b0a7bebfd351da, 0x0325261ba0bb3b54dd51e73d5752e4c42240205e4bf1cee19b3b04c2c6944654, 0x0a3b3f8e988beec2994ac1e1970dddfce296f4af57677e2d5d6e1d0f58864a64, 0x0ff6d6d358c3afca895ea5c4e7861ed1839c22fd1dbdc89168dc8a888cce03fb, 0x016f11f156a0c061c1d5502a3614d0407df140af55dbba456b186c40b8ccf4b9], \ + [0x01855a072a9428376cfd64bdc7ca033425315758f49ea485b15d718290d57fdb, 0x0823219f11b2d3d8995cf518083206d6b032e525efebb28347173a857de4917b, 0x05e2628407c2554d6f963847fc94fe337cfe9fd7d9a4765c2c2f4f44466f4297, 0x0bc90ec8dc06e4e93085d221849ac942b1da21a567075c9bbd33137e3d21d936, 0x00f6bcd001375094b206c368b85a87427e33b18a638f61b92f5797f35b27b483], \ + [0x02240f5265d51fcc47d4b5e99657c62c281a621105b60bde535369cf57b9fce3, 0x022c50143c5b09c8d84dc7ea04f92106de5668c819fbcbe2b079a6f65fbfa2e1, 0x058c169d6b53c4b12d376e54fbb206afdd4b3f7fc616bbc0242fa52bad332904, 0x0a92d0f7feb70ea83d105af37b826cee9f4673195e147c994c11a08ad543711b, 0x007ec81db746f19b568405b4198d0e928fc84aab77975a4e62ae057467d499f2], \ + [0x099345d797680263df3703cd47ba61648ca05b00c4e36651b5c5ea9f2b722ef0, 0x0f77b31d5d9c7efa1a584bb8fb7e996cc85789dd6d2a381d59d1e90a7cdbb9a7, 0x0753fa60bc853e5956de1d308208c91865c83694ba4f5da7ca6f51273607e808, 0x0f2d94d42741e900b20288b59bca3c620d23283aa3845d18f9f1bea139f7439a, 0x0eace4d73dff86ebd07d540f53462e82af315dfd7f9d16a4e74a8ff821b741f0], \ + [0x0b48f05ab6cca72feeeb42487202d2cb851406e4d01606128d87e3af0b5cffd7, 0x0ab61586e193c1faff5302f893e685aac3783b966fc55fd4459ee11d5476f135, 0x0fbc35a6eec52a7ea0cac835a998490f000d35a7fdd14a4692ac3b2fb896c915, 0x05d59b22a002231a41622c8b6c119f8fd04fe1790c88be8b3c14e14b0b4644b3, 0x0eebbbceffd456a992b64f7d08a6407fc6e50e61a8546debe2709e79dc2f830b], \ + [0x0cb649362954e881499a15e9424f74598aba1f4869b0a541e479460b988b93dc, 0x01a2c1b91716948b36c64027f814c424589e9bcb751173aa2d96fd24df8bfe7d, 0x065477226b997b6391678ee4d035928b62ae47bc726c7e12780fc1b0d55eb957, 0x082c9c59a958743d04adf02fda462ebab44a5d1e500ebc4087110fe8443a01d3, 0x06ed2a6f3623bf226b9b5d8610a08f0975d85917a39bd749abada04b8b9f4910], \ + [0x0d296535765fb6f57f10db89679254e5ee3c20db915fc6d2cfa7ce18c2db5994, 0x0401241fb0c0e3ab92e5ed651a7227a5827f0a3b37d569d654e3f6e4ee9afdc6, 0x0b0f93828aa86be71b98ef3a0cc5a4247ac63dfbf80ca726b25ebbfe2fc9f2a9, 0x0f556eaf433ee14740d35c9ee5103c439cd47a5e3d8ca3350f1a1cfc061f5d10, 0x005badc63641107c7149c4d9111b0adb1a36390a89b6b08c88b8806117a64817], \ + [0x027bb0e02e465218a4066d88ab3acc71e24cf52cf594a5e3e6709154478e0109, 0x0509ee58beeaca293017c0d3c3d92f8d60855ec82f83e23f1ccb10bb350f0d31, 0x09243d3e9240b9aa497d46182640b8fe7d832041a76081efdfa49f505b5d93e4, 0x0f7c328159d437d89dab8cfcec25beea769e6f5b65e542f1de35961c0041e6bb, 0x0e955f6624df2b78c04530a1b87ac09a03971ed185c3021af1c260f48e78fd7d], \ + [0x0fcf37ef120d96abe992a8438222f5db0f354d02b6275d06970c63cd90e21b03, 0x001dc9723a49bf995b31012d71b417323304c46d766b53a1b66d6d7113278984, 0x0025e92b05fcf120e00c79c0b36e5f97c6695823d9bce1a4b46d7e1c68f263f8, 0x0454a4f93b77db34f611fd65f4e7c6d5e3a5110cf1929ff0455d7b88dc509c25, 0x0004e19e4928bb8a54028c6d9a208cbccd857fa9f15bdcb3fdd213af97d0a55c], \ + [0x0038b51eb2b06e33a0011511cc8065b8c2a197162ca63a73c6ee3c3aca0024ac, 0x0712e49eab1ae3a5020e441c3a641367fa1155e227e577790b82436d76626d5b, 0x0eeddf0dd104a332962253f0a1b512ed0a4246faef321dbc14cb99bcb92b700b, 0x025cc088220ab762886b02dce29ecb8e9d83621b8bae268882615b50fd6649f4, 0x0fa575a75dce0240fb13abc28e29b4696f0f2cb5437b04b183fddf84c3288ffb]], + "matrix": [[0x0d55555555555555555555555555555566b9d03987ce5807f40f5295f822309b, 0x024924924924924924924924924924924c1fda8d84fecd43312732ba9f90d522, 0x0600000000000000000000000000000007d39db37d1cdad06106e529e2dc2f79, 0x038e38e38e38e38e38e38e38e38e38e392dc3786cee1b11330041605dbc4d9c3, 0x019999999999999999999999999999999bafe5c976b25c7bd59b704f6fb22ecb], \ + [0x024924924924924924924924924924924c1fda8d84fecd43312732ba9f90d522, 0x0600000000000000000000000000000007d39db37d1cdad06106e529e2dc2f79, 0x038e38e38e38e38e38e38e38e38e38e392dc3786cee1b11330041605dbc4d9c3, 0x019999999999999999999999999999999bafe5c976b25c7bd59b704f6fb22ecb, 0x0e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e9e9c28f8f13e317d0a3f42d225f6c0a9], \ + [0x0600000000000000000000000000000007d39db37d1cdad06106e529e2dc2f79, 0x038e38e38e38e38e38e38e38e38e38e392dc3786cee1b11330041605dbc4d9c3, 0x019999999999999999999999999999999bafe5c976b25c7bd59b704f6fb22ecb, 0x0e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e9e9c28f8f13e317d0a3f42d225f6c0a9, 0x0eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdcc650c1562fa6f2610dad82a8c0244], \ + [0x038e38e38e38e38e38e38e38e38e38e392dc3786cee1b11330041605dbc4d9c3, 0x019999999999999999999999999999999bafe5c976b25c7bd59b704f6fb22ecb, 0x0e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e9e9c28f8f13e317d0a3f42d225f6c0a9, 0x0eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdcc650c1562fa6f2610dad82a8c0244, 0x076276276276276276276276276276276c18248e23d4be8a50087c82524a130b], \ + [0x019999999999999999999999999999999bafe5c976b25c7bd59b704f6fb22ecb, 0x0e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e9e9c28f8f13e317d0a3f42d225f6c0a9, 0x0eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdcc650c1562fa6f2610dad82a8c0244, 0x076276276276276276276276276276276c18248e23d4be8a50087c82524a130b, 0x01249249249249249249249249249249260fed46c27f66a19893995d4fc86a91]] + }, + "nobackend": { + "R_F": 2, + "R_P": 2, + "t": 5, + "a": 3, + "round_constants": [[1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1]], + "matrix": [[1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1], \ + [1, 1, 1, 1, 1]] + } +} \ No newline at end of file diff --git a/pysnark/poseidon_hash.py b/pysnark/poseidon_hash.py new file mode 100644 index 0000000..881082f --- /dev/null +++ b/pysnark/poseidon_hash.py @@ -0,0 +1,130 @@ +import os +from pysnark import runtime +from pysnark.runtime import LinComb +from pysnark.fixedpoint import LinCombFxp +from pysnark.boolean import LinCombBool +from pysnark.poseidon_constants import poseidon_constants + +""" +Implements the Poseidon hash function with 128-bit security and 4-1 reduction +Currently supports the zkinterface and zkifbellman backends +""" + +# Load Poseidon parameters +try: + backend = os.environ["PYSNARK_BACKEND"] +except KeyError: + backend = "nobackend" + +if backend in poseidon_constants: + constants = poseidon_constants[backend] +else: + raise NotImplementedError("Poseidon is currently not implemented for this backend") + +R_F = constants["R_F"] +R_P = constants["R_P"] +t = constants["t"] +a = constants["a"] +round_constants = constants["round_constants"] +matrix = constants["matrix"] + +def matmul(x, y): + assert(len(x[0]) == len(y)) + + result = [[LinComb.ZERO for _ in range(len(y[0]))] for _ in range(len(x))] + + for i in range(len(x)): + for j in range(len(y[0])): + for k in range(len(y)): + result[i][j] += x[i][k] * y[k][j] + + return result + +def transpose(inputs): + result = [[None for _ in range(len(inputs))] for _ in range(len(inputs[0]))] + + for i in range(len(inputs)): + for j in range(len(inputs[0])): + result[j][i] = inputs[i][j] + + return result + +def permute(sponge): + """ + Runs the Poseidon permutation + Costs 400 constraints per permutation call for a power of 5 with a 4-1 reduction + """ + + # First full rounds + for r in range(R_F // 2): + # Add round constants + sponge = [x + y for (x,y) in zip(sponge, round_constants[r])] + # Full S-box layer + sponge = [x ** a for x in sponge] + # Mix layer + sponge = transpose(matmul(matrix, transpose([sponge])))[0] + # Reduce internal PySNARK representation of LinComb value modulo prime field + # Does not affect output circuit + for x in sponge: + x.value %= runtime.backend.get_modulus() + + # Partial rounds + for r in range(R_P): + # Add round constants + sponge = [x + y for (x,y) in zip(sponge, round_constants[R_F // 2 + r])] + # Partial S-box layer + sponge[0] = sponge[0] ** a + # Mix layer + sponge = transpose(matmul(matrix, transpose([sponge])))[0] + # Reduce internal PySNARK representation of LinComb value modulo prime field + # Does not affect output circuit + for x in sponge: + x.value %= runtime.backend.get_modulus() + + # Final full rounds + for r in range(R_F // 2): + # Add round constants + sponge = [x + y for (x,y) in zip(sponge, round_constants[R_F // 2 + R_P + r])] + # Full S-box layer + sponge = [x ** a for x in sponge] + # Mix layer + sponge = transpose(matmul(matrix, transpose([sponge])))[0] + # Reduce internal PySNARK representation of LinComb value modulo prime field + # Does not affect output circuit + for x in sponge: + x.value %= runtime.backend.get_modulus() + + return sponge + +def poseidon_hash(inputs): + """ + Runs the Poseidon hash on a list of LinCombs + """ + if not isinstance(inputs, list): + raise RuntimeError("Can only hash lists of LinCombs") + if not all(map(lambda x : isinstance(x, LinComb) or isinstance(x, LinCombFxp) or isinstance(x, LinCombBool), inputs)): + raise RuntimeError("Can only hash lists of LinCombs") + + # Convert inputs to LinCombs + inputs = [x.lc if isinstance(x, LinCombFxp) or isinstance(x, LinCombBool) else x for x in inputs] + + # Pad inputs + inputs_per_round = t - 1 + num_pad = inputs_per_round - len(inputs) % inputs_per_round + num_zeros = num_pad - 1 + inputs = inputs + [LinComb.ONE] + [LinComb.ZERO] * num_zeros + assert len(inputs) % inputs_per_round == 0 + + # Run hash + sponge = [LinComb.ZERO] * t + hash_rounds = len(inputs) // inputs_per_round + + for i in range(hash_rounds): + # Add inputs + round_inputs = inputs[i * inputs_per_round: (i + 1) * inputs_per_round] + sponge[1:] = [a + b for (a,b) in zip(sponge[1:], round_inputs)] + + # Run permutation + sponge = permute(sponge) + + return sponge[1:] \ No newline at end of file diff --git a/pysnark/runtime.py b/pysnark/runtime.py index 8755dc7..29e789f 100644 --- a/pysnark/runtime.py +++ b/pysnark/runtime.py @@ -1,10 +1,11 @@ -# Copytight (C) Meilof Veeningen, 2019 +# Copyright (C) Meilof Veeningen, 2019 import importlib import os import sys backend = None +backend_name = None backends = [ ["libsnark", "pysnark.libsnark.backend"], @@ -19,25 +20,29 @@ for mod in backends: if mod[1] in sys.modules: + backend_name = mod[0] backend = sys.modules[mod[1]] break if backend is None and "PYSNARK_BACKEND" in os.environ: - for mod in backends: - if os.environ["PYSNARK_BACKEND"]==mod[0]: - backend=importlib.import_module(mod[1]) - if backend is None: - print("*** PySNARK: unknown backend in environment variables: " + os.environ["PYSNARK_BACKEND"]) + for mod in backends: + if os.environ["PYSNARK_BACKEND"]==mod[0]: + backend_name = mod[0] + backend = importlib.import_module(mod[1]) + if backend is None: + print("*** PySNARK: unknown backend in environment variables: " + os.environ["PYSNARK_BACKEND"]) if backend is None: try: get_ipython() import pysnark.nobackend - backend=pysnark.nobackend + backend_name = "nobackend" + backend = pysnark.nobackend except: for mod in backends: try: - backend=importlib.import_module(mod[1]) + backend_name = mod[0] + backend = importlib.import_module(mod[1]) break except Exception as e: print("*** Error loading backend " + str(mod[1]) + ":", e) @@ -152,8 +157,11 @@ def _if_guard(*args, **kwargs): igprint = if_guard(print) -""" Add constraint v*w=y to the constraint system, and update running computation hash. """ def add_constraint(v,w,y,check=True): + """ + Add the constraint v * w = y to the constraint system + Updates running computation hash + """ if not guard is None: dummy = PrivVal(v.value*w.value-y.value) add_constraint_unsafe(v,w,y+dummy) @@ -161,7 +169,7 @@ def add_constraint(v,w,y,check=True): else: if v.value*w.value!=y.value: # note that we do the check over the integers - if check and not ignore_errors(): raise ValueError("constraint did not hold") + if check and not ignore_errors(): raise AssertionError("constraint did not hold") add_constraint_unsafe(v,w,y) @@ -172,7 +180,7 @@ def __init__(self, value, lc): def val(self): """ Creates a SNARK output for the current output and return its value """ - (self-PubVal(self.value)).assert_zero() + (self-PubVal(self.value)).assert_zero() return self.value def __repr__(self): @@ -182,173 +190,339 @@ def __deepcopy__(self, memodict): return self # self0, so other-self-1>=0 - def __lt__(self, other): return (other-self-1).check_positive() - def assert_lt(self, other, err=None): (other-self-1).assert_positive(err) + def __lt__(self, other): + return (other-self-1).check_positive() + + def assert_lt(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value >= other.value: + raise AssertionError(err if err is not None else str(self.value) + " is not less than " + str(other.value)) + + (other-self-1).assert_positive(err=err) # self<=other, so other-self>=0 - def __le__(self, other): return (other-self).check_positive() - def assert_le(self, other, err=None): (other-self).assert_positive(err) + def __le__(self, other): + return (other-self).check_positive() + + def assert_le(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value > other.value: + raise AssertionError(err if err is not None else str(self.value) + " is not less than or equal to " + str(other.value)) + + (other-self).assert_positive(err=err) - def __eq__(self, other): return (self-other).check_zero() - def assert_eq(self, other, err=None): (self-other).assert_zero(err) + def __eq__(self, other): + return (self-other).check_zero() + + def assert_eq(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value != other.value: + raise AssertionError(err if err is not None else str(self.value) + " is not equal to " + str(other.value)) + + (self-other).assert_zero(err=err) - def __ne__(self, other): return 1-(self==other) - def assert_ne(self, other, err=None): (self-other).assert_nonzero(err) + def __ne__(self, other): + return (self-other).check_nonzero() + + def assert_ne(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value == other.value: + raise AssertionError(err if err is not None else str(self.value) + " is equal to " + str(other.value)) + + (self-other).assert_nonzero(err=err) # self>other, so self-other>0, so self-other-1>=0 - def __gt__(self, other): return (self-other-1).check_positive() - def assert_gt(self, other, err=None): (self-other-1).assert_positive(err) - + def __gt__(self, other): + return (self-other-1).check_positive() + + def assert_gt(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value <= other.value: + raise AssertionError(err if err is not None else str(self.value) + " is not greater than " + str(other.value)) + + (self-other-1).assert_positive(err=err) + # self>=other, so self-other>=0 - def __ge__(self, other): return (self-other).check_positive() - def assert_ge(self, other, err=None): (self-other).assert_positive(err) + def __ge__(self, other): + return (self-other).check_positive() + + def assert_ge(self, other, err=None): + other = LinComb._ensurelc(other) + + if not ignore_errors(): + if self.value < other.value: + raise AssertionError(err if err is not None else str(self.value) + " is not greater than or equal to " + str(other.value)) + + (self-other).assert_positive(err=err) def __bool__(self): - raise NotImplementedError("Should not run bool() on a LinComb") - + raise NotImplementedError("Cannot call __bool__ on a LinComb. \ + Instead of if statements, use if_then_else from pysnark.branching") + def __add__(self, other): + """ + Adds a LinComb with an integer or another LinComb + Costs 0 constraints + """ + if isinstance(other, int): + return self + ConstVal(other) if isinstance(other, LinComb): - return LinComb(self.value+other.value, self.lc+other.lc) - elif is_base_value(other): - return self + other*LinComb.ONE - else: - return NotImplemented - - def __sub__(self, other): - return self+(-other) + return LinComb(self.value + other.value, self.lc + other.lc) + return NotImplemented + def __sub__(self, other): + """ + Subtracts an integer or another LinComb from a LinComb + Costs 0 constraints + """ + return self + (-other) + def __mul__(self, other): + """ + Multiplies a LinComb with an integer or another LinComb + Costs 0 constraints to multiply with an integer + Costs 1 constraint to multiply with a LinComb + """ + if isinstance(other, int): + return LinComb(self.value * other, self.lc * other) if isinstance(other, LinComb): - retval = PrivVal(self.value*other.value) + retval = PrivVal(self.value * other.value) add_constraint_unsafe(self, other, retval) return retval - elif is_base_value(other): - return LinComb(self.value*other, self.lc*other) - else: - return NotImplemented - - def __matmul__(self, other): return NotImplemented - + return NotImplemented + def __truediv__(self, other): - """ Proper division """ + """ + Divides a LinComb with an integer or another LinComb using integer division + Throws ValueError if values are not evenly divisible + Costs 0 constraints to divide with an integer + Costs 1 constraint to divide with a LinComb + """ + if isinstance(other, int): + if other == 0: + raise ValueError("Division by zero") + if is_guard() and (self.value % other == 0): + return LinComb(self.value // other, self.lc * backend.fieldinverse(other)) + if ignore_errors(): + return LinComb(0, self.lc * backend.fieldinverse(other)) + raise ValueError(str(self.value) + " is not properly divisible by " + str(other)) + if isinstance(other, LinComb): - if (is_guard()) and self.value % other.value == 0: - res = PrivVal(self.value/other.value) + if other.value == 0: + raise ValueError("Division by zero") + elif is_guard() and (self.value % other.value == 0): + res = PrivVal(self.value // other.value) elif ignore_errors(): res = PrivVal(0) else: raise ValueError(str(self.value) + " is not properly divisible by " + str(other.value)) add_constraint(other, res, self) return res - elif is_base_value(other): - if self.value % other != 0: - raise ValueError(str(self.value) + " is not properly divisible by " + str(other)) - return LinComb(self.value/other, self.lc*backend.fieldinverse(other)) - else: - return NotImplemented + + return NotImplemented def __floordiv__(self, other): - """ Division with rounding """ - return self.__divmod__(other)[0] + """ + Divides a LinComb with an integer or another LinComb using floor division + Costs 2 * bitlength + 4 constraints for floor division + """ + res = self.__divmod__(other) + if res is NotImplemented: + return NotImplemented + return res[0] def __mod__(self, other): - if other&(other-1)==0: - # this is faster for powers of two - return LinComb.from_bits(self.to_bits()[:other.bit_length()-1]) - - return self.__divmod__(other)[1] + """ + Returns the remainder of a LinComb divided with an integer or another LinComb + Costs 2 * bitlength + 4 constraints for modular division + """ + res = self.__divmod__(other) + if res is NotImplemented: + return NotImplemented + return res[1] def __divmod__(self, divisor): - """ Division by public value """ - - if not is_base_value(divisor): return NotImplemented - - if divisor==0: raise ValueError("division by zero") - - quo = PrivVal(self.value//divisor) - rem = PrivVal(self.value-quo.value*divisor) - - rem.assert_positive(divisor.bit_length()) - if divisor&(divisor-1)!=0: rem.assert_lt(divisor) # not needed for powers of two - quo.assert_positive() - (self-divisor*quo-rem).assert_zero() - - return (quo,rem) + """ + Divides a LinComb with an integer or another LinComb and returns the quotient and the remainder + Costs 2 * bitlength + 4 constraints to divide + """ + if isinstance(divisor, int): + divisor = ConstVal(divisor) + + if isinstance(divisor, LinComb): + if divisor.value == 0: + raise ValueError("Division by zero") + quo = PrivVal(self.value // divisor.value) + res = quo * divisor + rem = PrivVal(self.value - res.value) + + add_constraint(quo, divisor, self - rem) + rem.assert_lt(divisor) + quo.assert_positive() + return (quo,rem) + + return NotImplemented def __pow__(self, other, mod=None): - """ Exponentiation with public integral power p>=0 """ - if mod!=None: raise ValueError("cannot provide modulus") - if not is_base_value(other): return NotImplemented - if other<0: raise ValueError("exponent cannot be negative", other) - if other==0: return LinComb.ONE - if other==1: return self - return self*pow(self, other-1) + """ + Raises a LinComb to the power of an integer or a LinComb + Costs n constraints to raise to an integer power n + Costs 7 * bitlength + 1 constraints to raise to the power of a LinComb + """ + if mod != None: + raise ValueError("Cannot provide modulus") + if isinstance(other, int): + if other < 0: + raise ValueError("Exponent cannot be negative") + if other == 0: + return LinComb.ONE + if other == 1: + return self + return self * self ** (other - 1) + + if isinstance(other, LinComb): + # Obliviously apply repeated squaring + from .branching import if_then_else + + other_bits = other.to_bits() + + # Compute all powers of value to hide true exponent + powers = [self] + curr = self + for i in range(len(other_bits)): + curr = curr ** 2 + curr.value %= backend.get_modulus() + powers.append(curr) + + # Obliviously pick only the powers we need + multiplicands = [if_then_else(bit == 1, power, LinComb.ONE) for (bit, power) in zip(other_bits, powers)] + + # Multiply the powers together + res = LinComb.ONE + for multiplicand in multiplicands: + res *= multiplicand + res.value %= backend.get_modulus() + return res + + return NotImplemented def __lshift__(self, other): - """ Left-shift with public value """ - # TODO: extend to secret offset? - if not is_base_value(other): return NotImplemented - return self*(1<=0, self, -self) def __invert__(self): - # we do not want to do ~1=0 and ~0=1 since this is also not true for native ints - raise NotImplementedError("Operator ~ not supported. For binary not, use 1-x") + inverted_bits = [~x for x in self.to_bits()] + return LinComb.from_bits(inverted_bits) def __complex__(self): return NotImplemented def __int__(self): raise NotImplementedError("Should not run int() on LinComb") def __float__(self): return NotImplemented + def __matmul__(self, other): return NotImplemented + def __rmatmul__(self, other): return NotImplemented + def __round__(self, ndigits=None): return NotImplemented def __trunc__(self): return NotImplemented def __floor__(self): return NotImplemented def __ceil__(self): return NotImplemented - def assert_bool(self, err=None): - if (not ignore_errors()) and (self.value!=0 and self.value!=1): - raise ValueError(err if err is not None else "expected bool, got " + str(self.value)) + def to_bits(self, bits=None): + """ + Splits an integer LinComb into an bitlength-length array of LinCombBool bits + Raises AssertionError if LinComb cannot be represented with bitlength bits + Costs bitlength + 1 constraints to split a LinComb into bits + """ + from pysnark.boolean import PrivValBool - add_constraint(self, 1-self, LinComb.ZERO) + if bits is None: + bits = bitlength - def assert_bool_unsafe(self, err=None): - if (not ignore_errors()) and (self.value!=0 and self.value!=1): - raise ValueError(err if err is not None else "expected bool, got " + str(self.value)) + if not ignore_errors(): + if self.value < 0 or self.value.bit_length() > bits: + raise AssertionError(str(self.value) + " is not a " + str(bits) + "-bit positive integer") + + # Construct bits + bits = [PrivValBool((self.value & (1 << ix)) >> ix) for ix in range(bits)] - add_constraint_unsafe(self, LinComb.ONE_SAFE-self, LinComb.ZERO) - - def to_bits(self, bits=None): - if bits is None: bits=bitlength - - if (not ignore_errors()) and (self.value<0 or self.value.bit_length()>bits): - raise ValueError("value " + str(self.value) + " is not a " + str(bits) + "-bit positive integer") - - bits = [PrivVal((self.value&(1<>ix) for ix in range(bits)] - for bit in bits: bit.assert_bool_unsafe() - - (self-LinComb.from_bits(bits)).assert_zero() + # Check that bits are equal to self + (self - LinComb.from_bits(bits)).assert_zero() return bits @classmethod def from_bits(cls, bits): - return sum([biti*(1<>bitlength], check if it is positive. Note that this works on (bitlength+1)-length values so it works for __lt__, etc on bitlength-length values """ def check_positive(self, bits=None): - if bits is None: bits=bitlength - - if (is_guard()) and self.value.bit_length()<=bits: - ret = PrivVal(1 if self.value>=0 else 0) - abs = self.value if self.value>=0 else -self.value - bits = [PrivVal((abs&(1<>ix) for ix in range(bits)] + """ + Checks if a LinComb is a positive bitlength-bit integer + Costs bitlength + 2 constraints + """ + from pysnark.boolean import PrivValBool + + if bits is None: + bits = bitlength + + if is_guard() and self.value.bit_length() <= bits: + ret = PrivValBool(1 if self.value >= 0 else 0) + abs = self.value if self.value >= 0 else -self.value + + bits = [PrivValBool((abs & (1 << ix)) >> ix) for ix in range(bits)] elif ignore_errors(): - ret = PrivVal(0) - bits = [PrivVal(0) for _ in range(bits)] + ret = PrivValBool(0) + bits = [PrivValBool(0) for _ in range(bits)] else: - raise ValueError("value " + str(self.value) + " is not a " + str(bits) + "-bit integer") - - for bit in bits: bit.assert_bool_unsafe() + raise ValueError(str(self.value) + " is not a " + str(bits) + "-bit integer") - # if ret==1, then requires that 2*self=self+sum, so sum=self - # if ret==0, this requires that 0=self+sum, so sum=-self - add_constraint(2*ret, self, self+LinComb.from_bits(bits)) + # If ret == 1, then requires that 2 * self = self + sum, so sum = self + # If ret == 0, this requires that 0 = self + sum, so sum = -self + add_constraint(2 * ret, self, self + LinComb.from_bits(bits)) return ret def assert_positive(self, bits=None, err=None): - if bits is None: bits=bitlength - - if (not ignore_errors()) and (self.value<0 or self.value.bit_length()>bits): - raise ValueError(err if err is not None else "value " + str(self.value) + " is not a " + str(bits) + "-bit positive integer") + """ + Ensures a LinComb is a positive bitlength-bit integer + Costs bitlength + 1 constraints + """ + + if bits is None: + bits = bitlength - self.to_bits(bits) + if not ignore_errors(): + if self.value < 0 or self.value.bit_length() > bits: + raise AssertionError(err if err is not None else str(self.value) + " is not a " + str(bits) + "-bit positive integer") + + self.to_bits() def check_zero(self): - ret = PrivVal(1 if self.value==0 else 0) - - wit = PrivVal(backend.fieldinverse(self.value+ret.value)) # add ret.value so always nonzero + """ + Checks whether a LinComb is zero + Costs 2 constraints + """ + from pysnark.boolean import LinCombBool + + ret = PrivVal(1 if self.value == 0 else 0) + wit = PrivVal(backend.fieldinverse(self.value + (self.value == 0))) # Add self.value == 0 to prevent ZeroDivisionError # Trick from Pinocchio paper: if self is zero then ret=1 by first eq, # if self is nonzero then ret=0 by second eq - add_constraint_unsafe(self, wit, LinComb.ONE_SAFE-ret) + add_constraint_unsafe(self, wit, LinComb.ONE_SAFE - ret) add_constraint_unsafe(self, ret, LinComb.ZERO) - - return ret + + return LinCombBool(ret, False) + + def check_nonzero(self): + """ + Checks whether a LinComb is nonzero + Costs 2 constraints + """ + from pysnark.boolean import LinCombBool + + return ~self.check_zero() def assert_zero(self, err=None): + """ + Ensures a LinComb is zero + Costs 1 constraint + """ if (not ignore_errors()) and self.value!=0: - raise ValueError(err if err is not None else "value " + str(self.value) + " is not zero") + raise AssertionError(err if err is not None else str(self.value) + " is not zero") - add_constraint(LinComb.ZERO, LinComb.ZERO, self) + add_constraint(LinComb.ZERO, LinComb.ZERO, self) def assert_nonzero(self, err=None): + """ + Ensures a LinComb is nonzero + Costs 1 constraint + """ if (is_guard()) and self.value!=0: wit = PrivVal(backend.fieldinverse(self.value)) elif ignore_errors(): wit = PrivVal(0) else: - raise ValueError(err if err is not None else "value " + str(self.value) + " is not zero") + raise AssertionError(err if err is not None else str(self.value) + " is zero") add_constraint(self, wit, LinComb.ONE, check=False) - - def if_else(self, ifval, elseval): - from .branching import if_then_else - return if_then_else(self, ifval, elseval) - + + def assert_range(self, rangemin, rangemax, err=None): + """ + Ensures a LinComb is within the range [rangemin, rangemax] + Costs 2 * bitlength + 2 constraints + """ + rangemin = LinComb._ensurelc(rangemin) + rangemax = LinComb._ensurelc(rangemax) + + if not ignore_errors(): + if self.value < rangemin.value or self.value >= rangemax.value: + raise AssertionError(err if err is not None else str(self.value) + " is not in the range [" + str(rangemin.value) + "," + str(rangemax.value) + ")") + + # Use bounds check gadget from Bulletproofs + (self - rangemin).assert_positive() + (rangemax - self).assert_positive() + + @classmethod + def _ensurelc(cls, val): + if isinstance(val, LinComb): + return val + if isinstance(val, int): + return LinComb.ONE * val + raise RuntimeError("Wrong type for LinComb") + LinComb.ZERO = LinComb(0, backend.zero()) LinComb.ONE = LinComb(1, backend.one()) LinComb.ONE_SAFE = LinComb.ONE def PubVal(val): + """ + Create an instance variable + """ + if not isinstance(val, int): + raise RuntimeError("Wrong type for PubVal") return LinComb(val, backend.pubval(val)) def PrivVal(val): + """ + Create a witness variable + """ + if not isinstance(val, int): + raise RuntimeError("Wrong type for PrivVal") return LinComb(val, backend.privval(val)) +def ConstVal(val): + """ + Creates a LinComb representing a constant without creating a witness or instance variable + Should be used carefully. Using LinCombs instead of integers where not needed will hurt performance + """ + if not isinstance(val, int): + raise RuntimeError("Wrong type for ConstVal") + return LinComb(val, backend.one() * val) + def for_each_in(converter, struct): """ Recursively traversing all lists and tuples in struct, apply f to each element that is an instance of cls. Returns structure with f applied. """ @@ -494,171 +747,6 @@ def for_each_in(converter, struct): else: return converter(struct) -""" -Support for fixed-point computations -""" - -class LinCombFxp: - """ - Variable representing a fixed-point number. Number x is represented as integer - :math:`x * 2^r`, where r is the resolution :py:data:`VarFxp.res` - """ - - res = 8 - - def __init__(self, lc): - if not isinstance(lc, LinComb): raise RuntimeError("wrong type for LinCombFxp") - self.lc = lc - - @classmethod - def fromvar(cls, var, doconvert): - if not isinstance(var, LinComb): raise RuntimeError("wrong type for fromvar") - if doconvert: - return cls(var*(1<>LinCombFxp.res)) - - # mul error: should be in [-2^f,2^f] - diff = (1< self._ensurefxp(other).lc - def __ge__(self, other): return self.lc >= self._ensurefxp(other).lc - - def assert_lt(self, other, err=None): self.lc.assert_lt(self._ensurefxp(other).lc) - def assert_le(self, other, err=None): self.lc.assert_le(self._ensurefxp(other).lc) - def assert_eq(self, other, err=None): self.lc.assert_eq(self._ensurefxp(other).lc) - def assert_ne(self, other, err=None): self.lc.assert_ne(self._ensurefxp(other).lc) - def assert_gt(self, other, err=None): self.lc.assert_gt(self._ensurefxp(other).lc) - def assert_ge(self, other, err=None): self.lc.assert_ge(self._ensurefxp(other).lc) - - def __bool__(self): return bool(self.lc) - - def __pow__(self, other, mod=None): - """ Exponentiation with public integral power p>=0 """ - if mod!=None: raise ValueError("cannot provide modulus") - if not is_base_value(other): return NotImplemented - if other<0: raise ValueError("exponent cannot be negative", other) - if other==0: return LinCombFxp.fromvar(LinComb.ONE, True) - if other==1: return self - return self*pow(self, other-1) - - def __lshift__(self, other): return LinCombFxp(self.lc<>other) - - def __pos__(self): - return self - - def __abs__(self): - from .branching import if_then_else - return if_then_else(self>=0, self, -self) - - def __int__(self): raise NotImplementedError("Should not run int() on LinComb") - - def check_positive(self, *args, **kwargs): return self.lc.check_positive(*args, **kwargs) - def assert_positive(self, *args, **kwargs): self.lc.assert_positive(*args, **kwargs) - def check_zero(self): return self.lc.check_zero() - def assert_zero(self, *args, **kwargs): self.lc.assert_zero(*args, **kwargs) - def assert_nonzero(self, *args, **kwargs): self.lc.assert_nonzero(*args, **kwargs) - - def __if_then_else__(self, other, cond): - falsev = self._ensurefxp(other).lc - return LinCombFxp(falsev+(self.lc-falsev)*cond) - -def _tofxpval(val, doconvert): - if isinstance(val, float): - return int(val*(1< PrivVal(0)) == (1,2) + assert assert_linear_constraints(lambda: PrivVal(0) >= PrivVal(0)) == (1,2) + + def test_lincomb_check(self): + assert assert_constant_constraints(lambda: PrivVal(1).check_zero()) == 2 + assert assert_constant_constraints(lambda: PrivVal(1).check_nonzero()) == 2 + assert assert_linear_constraints(lambda: PrivVal(1).check_positive()) == (1,2) + + def test_lincomb_assertion(self): + assert assert_constant_constraints(lambda: PrivVal(0).assert_zero()) == 1 + assert assert_constant_constraints(lambda: PrivVal(1).assert_nonzero()) == 1 + + assert assert_linear_constraints(lambda: PrivVal(1).assert_positive()) == (1,1) + assert assert_linear_constraints(lambda: PrivVal(1).assert_range(PrivVal(0), PrivVal(2))) == (2, 2) + + assert assert_constant_constraints(lambda: PrivVal(0).assert_eq(PrivVal(0))) == 1 + assert assert_constant_constraints(lambda: PrivVal(0).assert_ne(PrivVal(1))) == 1 + + assert assert_linear_constraints(lambda: PrivVal(0).assert_lt(PrivVal(1))) == (1,1) + assert assert_linear_constraints(lambda: PrivVal(0).assert_le(PrivVal(1))) == (1,1) + + assert assert_linear_constraints(lambda: PrivVal(1).assert_gt(PrivVal(0))) == (1,1) + assert assert_linear_constraints(lambda: PrivVal(0).assert_ge(PrivVal(0))) == (1,1) + + def test_lincomb_bitwise(self): + assert assert_linear_constraints(lambda: PrivVal(0).to_bits()) == (1,1) + assert assert_constant_constraints(lambda: LinComb.from_bits([PrivVal(1), PrivVal(0), PrivVal(1)])) == 0 + + assert assert_constant_constraints(lambda: PrivVal(1) << 1) == 0 + assert assert_constant_constraints(lambda: PrivVal(1) << 2) == 0 + assert assert_linear_constraints(lambda: PrivVal(1) >> 1) == (1,1) + assert assert_linear_constraints(lambda: PrivVal(1) >> 2) == (1,1) + assert assert_linear_constraints(lambda: PrivVal(1) << PrivVal(1)) == (7,2) + assert assert_linear_constraints(lambda: PrivVal(1) >> PrivVal(1)) == (9,5) + + assert assert_constant_constraints(lambda: PrivVal(0) & 1) == 0 + assert assert_constant_constraints(lambda: PrivVal(0) | 1) == 0 + assert assert_constant_constraints(lambda: PrivVal(0) ^ 1) == 0 + + assert assert_linear_constraints(lambda: PrivVal(0) & PrivVal(1)) == (3,2) + assert assert_linear_constraints(lambda: PrivVal(0) | PrivVal(1)) == (3,2) + assert assert_linear_constraints(lambda: PrivVal(0) ^ PrivVal(1)) == (3,2) + + def test_lincombfxp_arithmetic(self): + assert assert_constant_constraints(lambda: LinCombFxp(PrivVal(1))) == 0 + + assert assert_constant_constraints(lambda: PrivValFxp(0) + 0) == 0 + assert assert_constant_constraints(lambda: PrivValFxp(0) - 0) == 0 + assert assert_constant_constraints(lambda: PrivValFxp(0) * 0) == 0 + assert assert_linear_constraints(lambda: PrivValFxp(1) / 1) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) // 1) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) % 1) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) ** 5) == (8,20) + + assert assert_constant_constraints(lambda: PrivValFxp(0) + PrivVal(0)) == 0 + assert assert_constant_constraints(lambda: PrivValFxp(0) - PrivVal(0)) == 0 + assert assert_constant_constraints(lambda: PrivValFxp(0) * PrivVal(0)) == 1 + assert assert_linear_constraints(lambda: PrivValFxp(1) / PrivVal(1)) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) // PrivVal(1)) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) % PrivVal(1)) == (2,4) + # assert assert_linear_constraints(lambda: PrivValFxp(1) ** PrivVal(0)) == 41 + # assert assert_linear_constraints(lambda: PrivValFxp(1) ** PrivVal(1)) == 41 + + assert assert_constant_constraints(lambda: PrivValFxp(0) + PrivValFxp(0)) == 0 + assert assert_constant_constraints(lambda: PrivValFxp(0) - PrivValFxp(0)) == 0 + assert assert_linear_constraints(lambda: PrivValFxp(0) * PrivValFxp(0)) == (2,5) + assert assert_linear_constraints(lambda: PrivValFxp(1) / PrivValFxp(1)) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) // PrivValFxp(1)) == (2,4) + assert assert_linear_constraints(lambda: PrivValFxp(1) % PrivValFxp(1)) == (2,4) + # assert assert_linear_constraints(lambda: PrivValFxp(1) ** PrivValFxp(0)) == 41 + # assert assert_linear_constraints(lambda: PrivValFxp(1) ** PrivValFxp(1)) == 41 + + def test_lincombfxp_comparison(self): + assert assert_constant_constraints(lambda: PrivValFxp(0) == 0) == 2 + assert assert_constant_constraints(lambda: PrivValFxp(0) != 0) == 2 + + assert assert_constant_constraints(lambda: PrivValFxp(0) == PrivVal(0)) == 2 + assert assert_constant_constraints(lambda: PrivValFxp(0) != PrivVal(1)) == 2 + + assert assert_linear_constraints(lambda: PrivValFxp(0) < PrivVal(0)) == (1,2) + assert assert_linear_constraints(lambda: PrivValFxp(0) <= PrivVal(0)) == (1,2) + + assert assert_linear_constraints(lambda: PrivValFxp(0) > PrivVal(0)) == (1,2) + assert assert_linear_constraints(lambda: PrivValFxp(0) >= PrivVal(0)) == (1,2) + + def test_lincombfxp_check(self): + assert assert_constant_constraints(lambda: PrivValFxp(1).check_zero()) == 2 + assert assert_constant_constraints(lambda: PrivValFxp(1).check_nonzero()) == 2 + assert assert_linear_constraints(lambda: PrivValFxp(1).check_positive()) == (1,2) + + def test_lincombfxp_assertion(self): + assert assert_constant_constraints(lambda: PrivValFxp(0).assert_zero()) == 1 + assert assert_constant_constraints(lambda: PrivValFxp(1).assert_nonzero()) == 1 + + assert assert_linear_constraints(lambda: PrivValFxp(1).assert_positive()) == (1,1) + assert assert_linear_constraints(lambda: PrivValFxp(1).assert_range(PrivVal(0), PrivVal(2))) == (2, 2) + + assert assert_constant_constraints(lambda: PrivValFxp(0).assert_eq(PrivVal(0))) == 1 + assert assert_constant_constraints(lambda: PrivValFxp(0).assert_ne(PrivVal(1))) == 1 + + assert assert_linear_constraints(lambda: PrivValFxp(0).assert_lt(PrivVal(1))) == (1,1) + assert assert_linear_constraints(lambda: PrivValFxp(0).assert_le(PrivVal(1))) == (1,1) + + assert assert_linear_constraints(lambda: PrivValFxp(1).assert_gt(PrivVal(0))) == (1,1) + assert assert_linear_constraints(lambda: PrivValFxp(0).assert_ge(PrivVal(0))) == (1,1) + + def test_lincombbool(self): + # Construct LinCombBool outside lambda, since construction costs 1 constraint + val = LinCombBool(PrivVal(1)) + + assert assert_constant_constraints(lambda: LinCombBool(PrivVal(1))) == 1 + assert assert_constant_constraints(lambda: -val) == 0 + + assert assert_constant_constraints(lambda: ~val) == 0 + assert assert_constant_constraints(lambda: val & val) == 1 + assert assert_constant_constraints(lambda: val | val) == 1 + assert assert_constant_constraints(lambda: val ^ val) == 1 + + assert assert_constant_constraints(lambda: val + PrivVal(2)) == 0 + assert assert_constant_constraints(lambda: val - PrivVal(2)) == 0 + assert assert_constant_constraints(lambda: val * PrivVal(2)) == 1 + assert assert_constant_constraints(lambda: val ** PrivVal(2)) == 2 \ No newline at end of file diff --git a/test/test_branching.py b/test/test_branching.py new file mode 100644 index 0000000..6f657b8 --- /dev/null +++ b/test/test_branching.py @@ -0,0 +1,31 @@ +import pytest +from pysnark.runtime import PrivVal +from pysnark.boolean import PrivValBool +from pysnark.fixedpoint import PrivValFxp +from pysnark.branching import if_then_else + +class TestLinCombFxp(): + def test_lincomb_branch(self): + assert if_then_else(PrivValBool(0), PrivVal(1), PrivVal(2)).val() == 2 + assert if_then_else(PrivValBool(1), PrivVal(1), PrivVal(2)).val() == 1 + + def test_lincombbool_branch(self): + assert if_then_else(PrivValBool(0), PrivValBool(1), PrivValBool(0)).val() == 0 + assert if_then_else(PrivValBool(1), PrivValBool(1), PrivValBool(0)).val() == 1 + + def test_lincombfxp_branch(self): + assert if_then_else(PrivValBool(0), PrivValFxp(1.5), PrivValFxp(2.5)).val() == 2.5 + assert if_then_else(PrivValBool(1), PrivValFxp(1.5), PrivValFxp(2.5)).val() == 1.5 + + def test_mixed_branch(self): + assert if_then_else(PrivValBool(0), PrivVal(1), PrivValFxp(2.5)).val() == 2.5 + assert if_then_else(PrivValBool(1), PrivValFxp(1.5), PrivValBool(1)).val() == 1.5 + assert if_then_else(PrivValBool(1), PrivValBool(1), PrivVal(2)).val() == 1 + + def test_branch_condition(self): + with pytest.raises(RuntimeError): + if_then_else(PrivVal(True), PrivVal(1), PrivVal(2)) + with pytest.raises(RuntimeError): + if_then_else(PrivVal(1), PrivVal(1), PrivVal(2)) + with pytest.raises(RuntimeError): + if_then_else(PrivValFxp(1), PrivVal(1), PrivVal(2)) \ No newline at end of file diff --git a/test/test_lincomb.py b/test/test_lincomb.py new file mode 100644 index 0000000..267f003 --- /dev/null +++ b/test/test_lincomb.py @@ -0,0 +1,148 @@ +from pysnark import runtime +from pysnark.runtime import PrivVal, PubVal + +class TestLinComb(): + def test_priv_val(self): + assert PrivVal(3).val() == 3 + + def test_pub_val(self): + assert PubVal(3).val() == 3 + + def test_add(self): + assert (PubVal(1) + 2).val() == 3 + assert (2 + PubVal(1)).val() == 3 + assert (PrivVal(1) + PrivVal(2)).val() == 3 + + def test_mul(self): + assert (PrivVal(2) * 2).val() == 4 + assert (2 * PrivVal(2)).val() == 4 + assert (PrivVal(2) * PrivVal(2)).val() == 4 + + def test_sub(self): + assert (PrivVal(2) - 1).val() == 1 + assert (2 - PrivVal(1)).val() == 1 + assert (PrivVal(2) - PrivVal(1)).val() == 1 + + def test_div_integer(self): + assert (PrivVal(4) / 2).val() == 2 + assert (4 / PrivVal(2)).val() == 2 + assert (PrivVal(4) / PrivVal(2)).val() == 2 + + def test_floor_div(self): + assert (PrivVal(4) // 2).val() == 2 + assert (4 // PrivVal(2)).val() == 2 + assert (PrivVal(4) // PrivVal(2)).val() == 2 + + assert (PrivVal(5) // 2).val() == 2 + assert (5 // PrivVal(2)).val() == 2 + assert (PrivVal(5) // PrivVal(2)).val() == 2 + + def test_mod(self): + assert (PrivVal(5) % 2).val() == 1 + assert (5 % PrivVal(2)).val() == 1 + assert (PrivVal(5) % PrivVal(2)).val() == 1 + + assert (PrivVal(5) % 1).val() == 0 + assert (5 % PrivVal(1)).val() == 0 + assert (PrivVal(5) % PrivVal(1)).val() == 0 + + def test_pow(self): + runtime.bitlength = 5 + + assert (PrivVal(2) ** 4).val() == 16 + assert (2 ** PrivVal(4)).val() == 16 + assert (PrivVal(2) ** PrivVal(4)).val() == 16 + + assert (PrivVal(2) ** 0).val() == 1 + assert (2 ** PrivVal(0)).val() == 1 + assert (PrivVal(2) ** PrivVal(0)).val() == 1 + + runtime.bitlength = 16 + + def test_rshift(self): + runtime.bitlength = 5 + + assert (PrivVal(2) << 2).val() == 8 + assert (2 << PrivVal(2)).val() == 8 + assert (PrivVal(2) << PrivVal(2)).val() == 8 + + runtime.bitlength = 16 + + def test_lshift(self): + runtime.bitlength = 5 + + assert (PrivVal(8) >> 2).val() == 2 + assert (8 >> PrivVal(2)).val() == 2 + assert (PrivVal(8) >> PrivVal(2)).val() == 2 + + runtime.bitlength = 16 + + def test_lt(self): + assert((PrivVal(1) < 2).val() == 1) + assert((1 < PrivVal(2)).val() == 1) + assert((PrivVal(1) < PrivVal(2)).val() == 1) + + assert((PrivVal(2) < 1).val() == 0) + assert((2 < PrivVal(1)).val() == 0) + assert((PrivVal(2) < PrivVal(1)).val() == 0) + + assert((PrivVal(1) < 1).val() == 0) + assert((1 < PrivVal(1)).val() == 0) + assert((PrivVal(1) < PrivVal(1)).val() == 0) + + def test_gt(self): + assert((PrivVal(2) > 1).val() == 1) + assert((2 > PrivVal(1)).val() == 1) + assert((PrivVal(2) > PrivVal(1)).val() == 1) + + assert((PrivVal(1) > 2).val() == 0) + assert((1 > PrivVal(2)).val() == 0) + assert((PrivVal(1) > PrivVal(2)).val() == 0) + + assert((PrivVal(1) > 1).val() == 0) + assert((1 > PrivVal(1)).val() == 0) + assert((PrivVal(1) > PrivVal(1)).val() == 0) + + def test_lte(self): + assert((PrivVal(1) <= 2).val() == 1) + assert((1 <= PrivVal(2)).val() == 1) + assert((PrivVal(1) <= PrivVal(2)).val() == 1) + + assert((PrivVal(2) <= 1).val() == 0) + assert((2 <= PrivVal(1)).val() == 0) + assert((PrivVal(2) <= PrivVal(1)).val() == 0) + + assert((PrivVal(1) <= 1).val() == 1) + assert((1 <= PrivVal(1)).val() == 1) + assert((PrivVal(1) <= PrivVal(1)).val() == 1) + + def test_gte(self): + assert((PrivVal(2) >= 1).val() == 1) + assert((2 >= PrivVal(1)).val() == 1) + assert((PrivVal(2) >= PrivVal(1)).val() == 1) + + assert((PrivVal(1) >= 2).val() == 0) + assert((1 >= PrivVal(2)).val() == 0) + assert((PrivVal(1) >= PrivVal(2)).val() == 0) + + assert((PrivVal(1) >= 1).val() == 1) + assert((1 >= PrivVal(1)).val() == 1) + assert((PrivVal(1) >= PrivVal(1)).val() == 1) + + def test_eq(self): + assert((PrivVal(2) == 2).val() == 1) + assert((2 == PrivVal(2)).val() == 1) + assert((PrivVal(2) == PrivVal(2)).val() == 1) + + assert((PrivVal(2) == 1).val() == 0) + assert((2 == PrivVal(1)).val() == 0) + assert((PrivVal(2) == PrivVal(1)).val() == 0) + + def test_neq(self): + assert((PrivVal(2) != 1).val() == 1) + assert((2 != PrivVal(1)).val() == 1) + assert((PrivVal(2) != PrivVal(1)).val() == 1) + + assert((PrivVal(2) != 2).val() == 0) + assert((2 != PrivVal(2)).val() == 0) + assert((PrivVal(2) != PrivVal(2)).val() == 0) diff --git a/test/test_lincomb_bitwise.py b/test/test_lincomb_bitwise.py new file mode 100644 index 0000000..eff024d --- /dev/null +++ b/test/test_lincomb_bitwise.py @@ -0,0 +1,33 @@ +import pytest +from pysnark.runtime import PrivVal +from pysnark.boolean import LinCombBool + +class TestLinCombBitwise(): + def test_to_bits(self): + bits = PrivVal(5).to_bits() + assert bits[3].val() == 0 + assert bits[2].val() == 1 + assert bits[1].val() == 0 + assert bits[0].val() == 1 + + def test_and(self): + assert (3 & PrivVal(7)).val() == 3 + assert (PrivVal(7) & 3).val() == 3 + assert (PrivVal(7) & PrivVal(3)).val() == 3 + assert (PrivVal(7) & PrivVal(0)).val() == 0 + assert (PrivVal(0) & PrivVal(7)).val() == 0 + + def test_or(self): + assert (3 | PrivVal(7)).val() == 7 + assert (PrivVal(7) | 3).val() == 7 + assert (PrivVal(7) | PrivVal(3)).val() == 7 + assert (PrivVal(7) | PrivVal(0)).val() == 7 + assert (PrivVal(0) | PrivVal(7)).val() == 7 + + def test_xor(self): + assert (3 ^ PrivVal(7)).val() == 4 + assert (PrivVal(7) ^ 3).val() == 4 + assert (PrivVal(7) ^ PrivVal(3)).val() == 4 + assert (PrivVal(7) ^ PrivVal(0)).val() == 7 + assert (PrivVal(0) ^ PrivVal(7)).val() == 7 + \ No newline at end of file diff --git a/test/test_lincomb_comparison.py b/test/test_lincomb_comparison.py new file mode 100644 index 0000000..835f22d --- /dev/null +++ b/test/test_lincomb_comparison.py @@ -0,0 +1,163 @@ +import pytest +from pysnark.runtime import PrivVal +from pysnark.boolean import LinCombBool + +class TestLinCombComparison(): + def test_eq(self): + assert (3 == PrivVal(3)).val() == 1 + assert (PrivVal(3) == 3).val() == 1 + assert (PrivVal(3) == PrivVal(3)).val() == 1 + assert isinstance(PrivVal(3) == 3, LinCombBool) + + assert (2 == PrivVal(3)).val() == 0 + assert (PrivVal(3) == 2).val() == 0 + assert (PrivVal(3) == PrivVal(2)).val() == 0 + assert (PrivVal(2) == PrivVal(3)).val() == 0 + assert isinstance(PrivVal(3) == 2, LinCombBool) + + def test_assert_eq(self): + PrivVal(3).assert_eq(3) + PrivVal(3).assert_eq(PrivVal(3)) + + with pytest.raises(AssertionError): + PrivVal(3).assert_eq(2) + with pytest.raises(AssertionError): + PrivVal(3).assert_eq(PrivVal(2)) + with pytest.raises(AssertionError): + PrivVal(2).assert_eq(PrivVal(3)) + + def test_ne(self): + assert (3 != PrivVal(2)).val() == 1 + assert (PrivVal(3) != 2).val() == 1 + assert (PrivVal(3) != PrivVal(2)).val() == 1 + assert (PrivVal(2) != PrivVal(3)).val() == 1 + assert isinstance(PrivVal(3) != 2, LinCombBool) + + assert (3 != PrivVal(3)).val() == 0 + assert (PrivVal(3) != 3).val() == 0 + assert (PrivVal(3) != PrivVal(3)).val() == 0 + assert isinstance(PrivVal(3) != 3, LinCombBool) + + def test_assert_ne(self): + PrivVal(3).assert_ne(2) + PrivVal(3).assert_ne(PrivVal(2)) + PrivVal(2).assert_ne(PrivVal(3)) + + with pytest.raises(AssertionError): + PrivVal(3).assert_ne(3) + with pytest.raises(AssertionError): + PrivVal(3).assert_ne(PrivVal(3)) + + def test_lt(self): + assert (3 < PrivVal(5)).val() == 1 + assert (PrivVal(3) < 5).val() == 1 + assert (PrivVal(3) < PrivVal(5)).val() == 1 + assert isinstance(PrivVal(3) < 5, LinCombBool) + + assert (3 < PrivVal(1)).val() == 0 + assert (PrivVal(3) < 1).val() == 0 + assert (PrivVal(3) < PrivVal(1)).val() == 0 + assert isinstance(PrivVal(3) < 1, LinCombBool) + + def test_assert_lt(self): + PrivVal(3).assert_lt(5) + PrivVal(3).assert_lt(PrivVal(5)) + + with pytest.raises(AssertionError): + PrivVal(3).assert_lt(1) + with pytest.raises(AssertionError): + PrivVal(3).assert_lt(PrivVal(1)) + with pytest.raises(AssertionError): + PrivVal(3).assert_lt(3) + with pytest.raises(AssertionError): + PrivVal(3).assert_lt(PrivVal(3)) + + def test_le(self): + assert (3 <= PrivVal(3)).val() == 1 + assert (3 <= PrivVal(5)).val() == 1 + assert (PrivVal(3) <= 3).val() == 1 + assert (PrivVal(3) <= 5).val() == 1 + assert (PrivVal(3) <= PrivVal(3)).val() == 1 + assert (PrivVal(3) <= PrivVal(5)).val() == 1 + assert isinstance(PrivVal(3) <= 5, LinCombBool) + + assert (3 <= PrivVal(1)).val() == 0 + assert (PrivVal(3) <= 1).val() == 0 + assert (PrivVal(3) <= PrivVal(1)).val() == 0 + assert isinstance(PrivVal(3) <= 1, LinCombBool) + + def test_assert_le(self): + PrivVal(3).assert_le(3) + PrivVal(3).assert_le(5) + PrivVal(3).assert_le(PrivVal(3)) + PrivVal(3).assert_le(PrivVal(5)) + + with pytest.raises(AssertionError): + PrivVal(3).assert_le(1) + with pytest.raises(AssertionError): + PrivVal(3).assert_le(PrivVal(1)) + + def test_gt(self): + assert (5 > PrivVal(3)).val() == 1 + assert (PrivVal(5) > 3).val() == 1 + assert (PrivVal(5) > PrivVal(3)).val() == 1 + assert isinstance(PrivVal(5) > 3, LinCombBool) + + assert (1 > PrivVal(3)).val() == 0 + assert (PrivVal(1) > 3).val() == 0 + assert (PrivVal(1) > PrivVal(3)).val() == 0 + assert isinstance(PrivVal(1) > 3, LinCombBool) + + def test_assert_gt(self): + PrivVal(5).assert_gt(3) + PrivVal(5).assert_gt(PrivVal(3)) + + with pytest.raises(AssertionError): + PrivVal(1).assert_gt(1) + with pytest.raises(AssertionError): + PrivVal(1).assert_gt(PrivVal(1)) + with pytest.raises(AssertionError): + PrivVal(1).assert_gt(3) + with pytest.raises(AssertionError): + PrivVal(1).assert_gt(PrivVal(3)) + + def test_ge(self): + assert (5 >= PrivVal(3)).val() == 1 + assert (5 >= PrivVal(3)).val() == 1 + assert (PrivVal(5) >= 3).val() == 1 + assert (PrivVal(5) >= 3).val() == 1 + assert (PrivVal(5) >= PrivVal(3)).val() == 1 + assert (PrivVal(5) >= PrivVal(3)).val() == 1 + assert isinstance(PrivVal(5) >= 3, LinCombBool) + + assert (1 >= PrivVal(3)).val() == 0 + assert (PrivVal(1) >= 3).val() == 0 + assert (PrivVal(1) >= PrivVal(3)).val() == 0 + assert isinstance(PrivVal(1) >= 3, LinCombBool) + + def test_assert_ge(self): + PrivVal(3).assert_ge(3) + PrivVal(5).assert_ge(3) + PrivVal(3).assert_ge(PrivVal(3)) + PrivVal(5).assert_ge(PrivVal(3)) + + with pytest.raises(AssertionError): + PrivVal(1).assert_ge(3) + with pytest.raises(AssertionError): + PrivVal(1).assert_ge(PrivVal(3)) + + def test_assert_range(self): + PrivVal(1).assert_range(PrivVal(1), PrivVal(2)) + with pytest.raises(AssertionError): + PrivVal(0).assert_range(PrivVal(1), PrivVal(2)) + with pytest.raises(AssertionError): + PrivVal(2).assert_range(PrivVal(1), PrivVal(2)) + + def test_check_zero(self): + assert PrivVal(0).check_zero().val() == 1 + assert PrivVal(1).check_zero().val() == 0 + + def test_check_nonzero(self): + assert PrivVal(0).check_nonzero().val() == 0 + assert PrivVal(1).check_nonzero().val() == 1 + \ No newline at end of file diff --git a/test/test_lincombbool.py b/test/test_lincombbool.py new file mode 100644 index 0000000..75e65b7 --- /dev/null +++ b/test/test_lincombbool.py @@ -0,0 +1,90 @@ +import pytest +from pysnark.runtime import PrivVal +from pysnark.boolean import PrivValBool, PubValBool + +class TestLinCombBool(): + def test_bool(self): + PubValBool(0) + PubValBool(1) + with pytest.raises(ValueError): + PubValBool(2) + with pytest.raises(RuntimeError): + PubValBool(2.5) + + def test_priv_val(self): + assert PrivValBool(0).val() == 0 + assert PrivValBool(1).val() == 1 + + def test_pub_val(self): + assert PubValBool(0).val() == 0 + assert PubValBool(1).val() == 1 + + def test_add(self): + assert (PrivValBool(1) + PrivValBool(1)).val() == 2 + assert (PrivVal(1) + PrivValBool(1)).val() == 2 + assert (PrivValBool(1) + PrivVal(1)).val() == 2 + assert (1 + PrivValBool(1)).val() == 2 + assert (PrivValBool(1) + 1).val() == 2 + + def test_mul(self): + assert (PrivValBool(1) * PrivValBool(0)).val() == 0 + assert (PrivVal(2) * PrivValBool(0)).val() == 0 + assert (PrivValBool(0) * PrivVal(2)).val() == 0 + + assert (PrivVal(2) * PrivValBool(1)).val() == 2 + assert (PrivValBool(1) * PrivVal(2)).val() == 2 + assert (2 * PrivValBool(1)).val() == 2 + assert (PrivValBool(1) * 2).val() == 2 + + def test_sub(self): + assert (PrivValBool(1) - PrivValBool(1)).val() == 0 + assert (PrivVal(1) - PrivValBool(1)).val() == 0 + assert (PrivValBool(1) - PrivVal(1)).val() == 0 + assert (1 - PrivValBool(1)).val() == 0 + assert (PrivValBool(1) - 1).val() == 0 + + def test_not(self): + assert (~PubValBool(0)).val() == 1 + assert (~PubValBool(1)).val() == 0 + + def test_and(self): + assert (PubValBool(0) & 0).val() == 0 + assert (PubValBool(0) & 1).val() == 0 + assert (PubValBool(1) & 0).val() == 0 + assert (PubValBool(1) & 1).val() == 1 + + assert (PubValBool(1) & 2).val() == 1 + assert (PubValBool(1) & True).val() == 1 + + assert (PubValBool(0) & PubValBool(0)).val() == 0 + assert (PubValBool(0) & PubValBool(1)).val() == 0 + assert (PubValBool(1) & PubValBool(0)).val() == 0 + assert (PubValBool(1) & PubValBool(1)).val() == 1 + + def test_or(self): + assert (PubValBool(0) | 0).val() == 0 + assert (PubValBool(0) | 1).val() == 1 + assert (PubValBool(1) | 0).val() == 1 + assert (PubValBool(1) | 1).val() == 1 + + assert (PubValBool(1) | 2).val() == 1 + assert (PubValBool(1) | True).val() == 1 + + assert (PubValBool(0) | PubValBool(0)).val() == 0 + assert (PubValBool(0) | PubValBool(1)).val() == 1 + assert (PubValBool(1) | PubValBool(0)).val() == 1 + assert (PubValBool(1) | PubValBool(1)).val() == 1 + + def test_xor(self): + assert (PubValBool(0) ^ 0).val() == 0 + assert (PubValBool(0) ^ 1).val() == 1 + assert (PubValBool(1) ^ 0).val() == 1 + assert (PubValBool(1) ^ 1).val() == 0 + + assert (PubValBool(1) ^ 2).val() == 0 + assert (PubValBool(1) ^ True).val() == 0 + + assert (PubValBool(0) ^ PubValBool(0)).val() == 0 + assert (PubValBool(0) ^ PubValBool(1)).val() == 1 + assert (PubValBool(1) ^ PubValBool(0)).val() == 1 + assert (PubValBool(1) ^ PubValBool(1)).val() == 0 \ No newline at end of file diff --git a/test/test_lincombfxp.py b/test/test_lincombfxp.py new file mode 100644 index 0000000..56aa064 --- /dev/null +++ b/test/test_lincombfxp.py @@ -0,0 +1,138 @@ +import pytest +from pysnark import runtime +from pysnark import fixedpoint +from pysnark.runtime import PrivVal +from pysnark.fixedpoint import PrivValFxp, PubValFxp + +class TestLinCombFxp(): + def test_fixed_point(self): + assert PrivValFxp(1).lc.value == 1 << fixedpoint.resolution + assert PrivValFxp(1.0).lc.value == 1 << fixedpoint.resolution + + def test_priv_val(self): + assert PrivValFxp(3).val() == 3 + assert PrivValFxp(3.125).val() == 3.125 + + def test_pub_val(self): + assert PubValFxp(3).val() == 3 + assert PubValFxp(3.125).val() == 3.125 + + def test_resolution(self): + fixedpoint.resolution = 4 + + PubValFxp(3.0625) + with pytest.warns(UserWarning): + PubValFxp(3.06255) + + fixedpoint.resolution = 8 + + with pytest.warns(UserWarning): + PubValFxp(3.14) + + def test_add(self): + assert (PrivValFxp(1.0) + 2).val() == 3.0 + assert (PrivValFxp(1.0) + 2.0).val() == 3.0 + assert (2 + PrivValFxp(1.0)).val() == 3.0 + assert (2.0 + PrivValFxp(1.0)).val() == 3.0 + assert (PrivValFxp(1.0) + PrivValFxp(2.0)).val() == 3.0 + assert (PrivValFxp(1.0) + PrivVal(2)).val() == 3.0 + assert (PrivVal(2) + PrivValFxp(1.0)).val() == 3.0 + + def test_mul(self): + assert (PrivValFxp(2.0) * 2).val() == 4 + assert (PrivValFxp(2.0) * 2.0).val() == 4 + assert (2 * PrivValFxp(2.0)).val() == 4 + assert (2.0 * PrivValFxp(2.0)).val() == 4 + assert (PrivValFxp(2.0) * PrivValFxp(2.0)).val() == 4 + assert (PrivValFxp(2.0) * PrivVal(2)).val() == 4 + assert (PrivVal(2) * PrivValFxp(2.0)).val() == 4 + + def test_sub(self): + assert (PrivValFxp(2.0) - 1).val() == 1.0 + assert (PrivValFxp(2.0) - 1.0).val() == 1.0 + assert (2 - PrivValFxp(1.0)).val() == 1.0 + assert (2.0 - PrivValFxp(1.0)).val() == 1.0 + assert (PrivValFxp(2.0) - PrivValFxp(1.0)).val() == 1.0 + assert (PrivValFxp(2.0) - PrivVal(1)).val() == 1.0 + assert (PrivVal(2) - PrivValFxp(1.0)).val() == 1.0 + + def test_div_integer(self): + assert (PrivValFxp(4.0) / 2).val() == 2.0 + assert (PrivValFxp(4.0) / 2.0).val() == 2.0 + assert (4 / PrivValFxp(2.0)).val() == 2.0 + assert (4.0 / PrivValFxp(2.0)).val() == 2.0 + assert (PrivValFxp(4.0) / PrivValFxp(2.0)).val() == 2.0 + assert (PrivValFxp(4.0) / PrivVal(2)).val() == 2.0 + assert (PrivVal(4) / PrivValFxp(2.0)).val() == 2.0 + + def test_div_fraction(self): + assert (PrivValFxp(5.0) / 2).val() == 2.5 + assert (PrivValFxp(5.0) / 2.0).val() == 2.5 + assert (5 / PrivValFxp(2.0)).val() == 2.5 + assert (5.0 / PrivValFxp(2.0)).val() == 2.5 + assert (PrivValFxp(5.0) / PrivValFxp(2.0)).val() == 2.5 + assert (PrivValFxp(5.0) / PrivVal(2)).val() == 2.5 + assert (PrivVal(5) / PrivValFxp(2.0)).val() == 2.5 + + def test_floor_div(self): + assert (PrivValFxp(5.0) // 2).val() == 2.0 + assert (PrivValFxp(5.0) // 2.0).val() == 2.0 + assert (5 // PrivValFxp(2.0)).val() == 2.0 + assert (5.0 // PrivValFxp(2.0)).val() == 2.0 + assert (PrivValFxp(5.0) // PrivValFxp(2.0)).val() == 2.0 + assert (PrivValFxp(5.0) // PrivVal(2)).val() == 2.0 + assert (PrivVal(5) // PrivValFxp(2.0)).val() == 2.0 + + def test_mod(self): + assert (PrivValFxp(5) % 2).val() == 1.0 + assert (PrivValFxp(5) % 2.0).val() == 1.0 + assert (5 % PrivValFxp(2)).val() == 1.0 + assert (5.0 % PrivValFxp(2)).val() == 1.0 + assert (PrivValFxp(5) % PrivValFxp(2)).val() == 1.0 + assert (PrivValFxp(5) % PrivVal(2)).val() == 1.0 + assert (PrivVal(5) % PrivValFxp(2)).val() == 1.0 + + assert (PrivValFxp(5) % 1).val() == 0.0 + assert (PrivValFxp(5) % 1.0).val() == 0.0 + assert (5 % PrivValFxp(1)).val() == 0.0 + assert (5.0 % PrivValFxp(1)).val() == 0.0 + assert (PrivValFxp(5) % PrivValFxp(1)).val() == 0.0 + assert (PrivValFxp(5) % PrivVal(1)).val() == 0.0 + assert (PrivVal(5) % PrivValFxp(1)).val() == 0.0 + + def test_pow(self): + assert (PrivValFxp(2) ** 2).val() == 4.0 + # assert (PrivValFxp(2) ** 2.0).val() == 4.0 + # assert (2 ** PrivValFxp(2)).val() == 4.0 + # assert (2.0 ** PrivValFxp(2)).val() == 4.0 + # assert (PrivValFxp(2) ** PrivValFxp(2)).val() == 4.0 + # assert (PrivValFxp(2) ** PrivVal(2)).val() == 4.0 + # assert (PrivVal(2) ** PrivValFxp(2)).val() == 4.0 + + assert (PrivValFxp(2) ** 0).val() == 1.0 + # assert (PrivValFxp(2) ** 0.0).val() == 1.0 + # assert (2 ** PrivValFxp(0)).val() == 1.0 + # assert (2.0 ** PrivValFxp(0)).val() == 1.0 + # assert (PrivValFxp(2) ** PrivValFxp(0)).val() == 1.0 + # assert (PrivValFxp(2) ** PrivVal(0)).val() == 1.0 + # assert (PrivVal(2) ** PrivValFxp(0)).val() == 1.0 + + def test_rshift(self): + pass + # assert (PrivValFxp(2.0) << 2).val() == 8.0 + # assert (PrivValFxp(2.0) << 2.0).val() == 8.0 + # assert (2 << PrivValFxp(2.0)).val() == 8.0 + # assert (2.0 << PrivValFxp(2.0)).val() == 8.0 + # assert (PrivValFxp(2.0) << PrivValFxp(2.0)).val() == 8.0 + # assert (PrivValFxp(2.0) << PrivVal(2)).val() == 8.0 + # assert (PrivVal(2) << PrivValFxp(2.0)).val() == 8.0 + + def test_lshift(self): + pass + # assert (PrivValFxp(8.0) >> 2).val() == 2.0 + # assert (PrivValFxp(8.0) >> 2.0).val() == 2.0 + # assert (8 >> PrivValFxp(2.0)).val() == 2.0 + # assert (8.0 >> PrivValFxp(2.0)).val() == 2.0 + # assert (PrivValFxp(8.0) >> PrivValFxp(2.0)).val() == 2.0 + # assert (PrivValFxp(8.0) >> PrivVal(2)).val() == 2.0 + # assert (PrivVal(8.0) >> PrivValFxp(2.0)).val() == 2.0 \ No newline at end of file diff --git a/test/test_poseidon_hash.py b/test/test_poseidon_hash.py new file mode 100644 index 0000000..d00c13a --- /dev/null +++ b/test/test_poseidon_hash.py @@ -0,0 +1,59 @@ +import pytest +import pysnark +from pysnark.runtime import PrivVal +from pysnark.fixedpoint import PrivValFxp +from pysnark.boolean import PrivValBool +from pysnark.poseidon_constants import poseidon_constants + +@pytest.mark.skipif(pysnark.runtime.backend_name not in poseidon_constants, reason="Unsupported backend") +class TestPoseidonHash(): + # The poseidon_hash module throws an error if a backend is not supported + # We import from poseidon_hash inside the method so that we only import when + # the current backend is supported, preventing exceptions being raised + + @pytest.mark.skipif(pysnark.runtime.backend_name != "zkinterface", reason="Unsupported backend") + def test_zkinterface_permutation(self): + from pysnark.poseidon_hash import permute + output = permute([PrivVal(0), PrivVal(1), PrivVal(2), PrivVal(3), PrivVal(4)]) + result = [0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465, \ + 0x1148aaef609aa338b27dafd89bb98862d8bb2b429aceac47d86206154ffe053d, \ + 0x24febb87fed7462e23f6665ff9a0111f4044c38ee1672c1ac6b0637d34f24907, \ + 0x0eb08f6d809668a981c186beaf6110060707059576406b248e5d9cf6e78b3d3e, \ + 0x07748bc6877c9b82c8b98666ee9d0626ec7f5be4205f79ee8528ef1c4a376fc7] + print(output) + assert all([x.val() == y for (x,y) in zip(output, result)]) + + @pytest.mark.skipif(pysnark.runtime.backend_name != "zkifbellman", reason="Unsupported backend") + def test_zkifbellman_permutation(self): + from pysnark.poseidon_hash import permute + output = permute([PrivVal(0), PrivVal(1), PrivVal(2), PrivVal(3), PrivVal(4)]) + result = [0x2a918b9c9f9bd7bb509331c81e297b5707f6fc7393dcee1b13901a0b22202e18, \ + 0x65ebf8671739eeb11fb217f2d5c5bf4a0c3f210e3f3cd3b08b5db75675d797f7, \ + 0x2cc176fc26bc70737a696a9dfd1b636ce360ee76926d182390cdb7459cf585ce, \ + 0x4dc4e29d283afd2a491fe6aef122b9a968e74eff05341f3cc23fda1781dcb566, \ + 0x03ff622da276830b9451b88b85e6184fd6ae15c8ab3ee25a5667be8592cce3b1] + assert all([x.val() == y for (x,y) in zip(output, result)]) + + @pytest.mark.skipif(pysnark.runtime.backend_name != "zkifbulletproofs", reason="Unsupported backend") + def test_zkifbulletproofs_permutation(self): + from pysnark.poseidon_hash import permute + output = permute([PrivVal(0), PrivVal(1), PrivVal(2), PrivVal(3), PrivVal(4)]) + result = [0x2a918b9c9f9bd7bb509331c81e297b5707f6fc7393dcee1b13901a0b22202e18, \ + 0x65ebf8671739eeb11fb217f2d5c5bf4a0c3f210e3f3cd3b08b5db75675d797f7, \ + 0x2cc176fc26bc70737a696a9dfd1b636ce360ee76926d182390cdb7459cf585ce, \ + 0x4dc4e29d283afd2a491fe6aef122b9a968e74eff05341f3cc23fda1781dcb566, \ + 0x03ff622da276830b9451b88b85e6184fd6ae15c8ab3ee25a5667be8592cce3b1] + assert all([x.val() == y for (x,y) in zip(output, result)]) + + def test_lincombfxp(self): + from pysnark.poseidon_hash import permute + output = permute([PrivVal(0), PrivVal(1), PrivVal(2), PrivVal(3), PrivVal(4)]) + + def test_lincombbool(self): + from pysnark.poseidon_hash import poseidon_hash + poseidon_hash([PrivValBool(0), PrivValBool(1), PrivValBool(0), PrivValBool(1), PrivValBool(0)]) + + def test_int(self): + from pysnark.poseidon_hash import poseidon_hash + with pytest.raises(RuntimeError): + output = poseidon_hash([PrivVal(0), PrivVal(1), PrivVal(2), PrivVal(3), 4]) \ No newline at end of file