Esempio n. 1
0
    def generate_proof(self, project_dir: str, contract: str, function: str, priv_values: List, in_vals: List, out_vals: List[Union[int, CipherValue]]) -> List[int]:
        """
        Generate a NIZK-proof using the provided circuit for the given arguments.

        Note: circuit arguments must be in the same order as they are declared inside the circuit. (i.e. in execution order)

        :param project_dir: directory where the manifest and the prover keys are located
        :param contract: contract of which the function which requires verification is part of
        :param function: the contract member function for which a proof needs to be generated
        :param priv_values: private/auxiliary circuit inputs in correct order
        :param in_vals: public circuit inputs in correct order
        :param out_vals: public circuit outputs in correct order
        :raise ProofGenerationError: if proof generation fails
        :return: the proof, serialized into an uint256 array
        """
        for i in range(len(priv_values)):
            arg = priv_values[i]
            assert not isinstance(arg, Value) or isinstance(arg, (RandomnessValue, AddressValue))
            if isinstance(arg, AddressValue):
                priv_values[i] = int.from_bytes(arg.val, byteorder='big')

        zk_print(f'Generating proof for {contract}.{function}')
        zk_print(f'[priv: {Value.collection_to_string(priv_values)}] '
                 f'[in: {Value.collection_to_string(in_vals)}] [out: {Value.collection_to_string(out_vals)}]', verbosity_level=2)

        priv_values, in_vals, out_vals = Value.unwrap_values(Value.flatten(priv_values)), Value.unwrap_values(in_vals), Value.unwrap_values(out_vals)

        # Check for overflows
        for arg in priv_values + in_vals + out_vals:
            assert int(arg) < bn128_scalar_field, 'argument overflow'

        with time_measure(f'generate_proof', True):
            verify_dir = cfg.get_circuit_output_dir_name(cfg.get_verification_contract_name(contract, function))
            return self._generate_proof(os.path.join(project_dir, verify_dir), priv_values, in_vals, out_vals)
Esempio n. 2
0
def compile_zkay_file(input_file_path: str, output_dir: str, import_keys: bool = False, **kwargs):
    """
    Parse, type-check and compile the given zkay contract file.

    :param input_file_path: path to the zkay contract file
    :param output_dir: path to a directory where the compilation output should be generated
    :param import_keys: | if false, zk-snark of all modified circuits will be generated during compilation
                        | if true, zk-snark keys for all circuits are expected to be already present in the output directory, and the compilation will use the provided keys to generate the verification contracts
                        | This option is mostly used internally when connecting to a zkay contract provided by a 3rd-party
    :raise ZkayCompilerError: if any compilation stage fails
    :raise RuntimeError: if import_keys is True and zkay file, manifest file or any of the key files is missing
    """
    code = read_file(input_file_path)

    # log specific features of compiled program
    my_logging.data('originalLoc', lines_of_code(code))
    m = re.search(r'\/\/ Description: (.*)', code)
    if m:
        my_logging.data('description', m.group(1))
    m = re.search(r'\/\/ Domain: (.*)', code)
    if m:
        my_logging.data('domain', m.group(1))
    _, filename = os.path.split(input_file_path)

    # compile
    with time_measure('compileFull'):
        cg, _ = compile_zkay(code, output_dir, import_keys, **kwargs)
Esempio n. 3
0
    def generate_circuits(self, *, import_keys: bool):
        """
        Generate circuit code and verification contracts based on the provided circuits and proving scheme.

        :param import_keys: if false, new verification and prover keys will be generated, otherwise key files for all verifiers
                            are expected to be already present in the respective output directories
        """
        # Generate proof circuit code

        # Compile circuits
        c_count = len(self.circuits_to_prove)
        zk_print(f'Compiling {c_count} circuits...')

        gen_circs = functools.partial(self._generate_zkcircuit, import_keys)
        with time_measure('circuit_compilation', True):
            if cfg.is_unit_test:
                modified = list(map(gen_circs, self.circuits_to_prove))
            else:
                with Pool(processes=self.p_count) as pool:
                    modified = pool.map(gen_circs, self.circuits_to_prove)

        if import_keys:
            for path in self.get_all_key_paths():
                if not os.path.exists(path):
                    raise RuntimeError("Zkay contract import failed: Missing keys")
        else:
            modified_circuits_to_prove = [circ for t, circ in zip(modified, self.circuits_to_prove)
                                          if t or not all(map(os.path.exists, self._get_vk_and_pk_paths(circ)))]

            # Generate keys in parallel
            zk_print(f'Generating keys for {c_count} circuits...')
            with time_measure('key_generation', True):
                if self.parallel_keygen and not cfg.is_unit_test:
                    counter = Value('i', 0)
                    with Pool(processes=self.p_count, initializer=self.__init_worker, initargs=(counter, c_count,)) as pool:
                        pool.map(self._generate_keys_par, modified_circuits_to_prove)
                else:
                    for circ in modified_circuits_to_prove:
                        self._generate_keys(circ)

        with print_step('Write verification contracts'):
            for circuit in self.circuits_to_prove:
                vk = self._parse_verification_key(circuit)
                pk_hash = self._get_prover_key_hash(circuit)
                with open(os.path.join(self.output_dir, circuit.verifier_contract_filename), 'w') as f:
                    primary_inputs = self._get_primary_inputs(circuit)
                    f.write(self.proving_scheme.generate_verification_contract(vk, circuit, primary_inputs, pk_hash))
Esempio n. 4
0
def transaction_benchmark_ctx(contract_dir: str, log_filename='log') -> ContextManager[Any]:
    use_configuration_from_manifest(contract_dir)
    cfg.verbosity = 0
    cfg.log_dir = contract_dir
    log_file = my_logging.get_log_file(filename=log_filename, include_timestamp=False, label=None)
    my_logging.prepare_logger(log_file)
    with time_measure('all_transactions', should_print=True):
        yield load_transaction_interface_from_directory(contract_dir)
        pass
Esempio n. 5
0
    def test_timer_context_manager(self):
        log_file = base_log_file + '_context_manager'
        my_logging.prepare_logger(log_file)
        my_logging.shutdown()

        with time_measure('mykey2'):
            time.sleep(0.5)

        content = read_file(log_file + '_data.log')
        d = json.loads(content)
        self.assertAlmostEqual(0.5, d['value'], 1)
Esempio n. 6
0
    def _dec(self, cipher: Tuple[int, ...], sk: Any) -> Tuple[int, List[int]]:
        with time_measure("elgamal_decrypt"):
            c1 = babyjubjub.Point(babyjubjub.Fq(cipher[0]),
                                  babyjubjub.Fq(cipher[1]))
            c2 = babyjubjub.Point(babyjubjub.Fq(cipher[2]),
                                  babyjubjub.Fq(cipher[3]))
            shared_secret = c1 * babyjubjub.Fr(sk)
            plain_embedded = c2 + shared_secret.negate()
            plain = self._de_embed(plain_embedded)

        # TODO randomness misused for the secret key, which is an extremely ugly hack...
        return plain, [sk]
Esempio n. 7
0
    def _generate_proof(self, verifier_dir: str, priv_values: List[int],
                        in_vals: List[int], out_vals: List[int]) -> List[int]:
        args = list(map(int, in_vals + out_vals + priv_values))

        # Generate proof in temporary directory
        with TemporaryDirectory() as tempd:
            proof_path = os.path.join(tempd, 'proof.out')
            try:
                with time_measure("jsnark_prepare_proof"):
                    jsnark.prepare_proof(verifier_dir, tempd, args)

                with time_measure("libsnark_gen_proof"):
                    libsnark.generate_proof(verifier_dir, tempd, proof_path,
                                            self.proving_scheme)
            except SubprocessError as e:
                raise ProofGenerationError(e.args)

            with open(proof_path) as f:
                proof_lines = f.read().splitlines()
        proof = list(map(lambda x: int(x, 0), proof_lines))
        return proof
Esempio n. 8
0
 def _deploy_dependencies(self, sender: Union[bytes, str], project_dir: str, verifier_names: List[str]) -> Dict[str, AddressValue]:
     # Deploy verification contracts if not already done
     vf = {}
     for verifier_name in verifier_names:
         with log_context('constructor'):
             with log_context(f'{verifier_name}'):
                 filename = os.path.join(project_dir, f'{verifier_name}.sol')
                 cout = self.compile_contract(filename, verifier_name, self.lib_addresses)
                 with time_measure("transaction_full"):
                     vf[verifier_name] = AddressValue(self._deploy_contract(sender, cout).address)
     for crypto_params in cfg.all_crypto_params():
         pki_contract_name = cfg.get_pki_contract_name(crypto_params)
         pki_contract_address = self.pki_contract(crypto_params.crypto_name).address
         vf[pki_contract_name] = AddressValue(pki_contract_address)
     return vf