From 4e2c9d44fc6ca821179ae485d185f3b92decf008 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Wed, 18 Sep 2024 09:28:29 +0200 Subject: [PATCH] proofs generation and cairo0 programs --- examples/proofs/cpu_air_params.json | 28 ++++ examples/proofs/cpu_air_prover_config.json | 9 ++ examples/proofs/dex/cairo0_fibonacci.cairo | 44 +++++ examples/proofs/fibonacci_input.json | 3 + examples/proofs/generate,py | 153 ++++++++++++++++++ .../proofs/recursive/cairo0_fibonacci.cairo | 44 +++++ .../cairo0_fibonacci.cairo | 44 +++++ examples/proofs/small/cairo0_fibonacci.cairo | 44 +++++ .../proofs/starknet/cairo0_fibonacci.cairo | 44 +++++ .../cairo0_fibonacci.cairo | 44 +++++ 10 files changed, 457 insertions(+) create mode 100644 examples/proofs/cpu_air_params.json create mode 100644 examples/proofs/cpu_air_prover_config.json create mode 100644 examples/proofs/dex/cairo0_fibonacci.cairo create mode 100644 examples/proofs/fibonacci_input.json create mode 100644 examples/proofs/generate,py create mode 100644 examples/proofs/recursive/cairo0_fibonacci.cairo create mode 100644 examples/proofs/recursive_with_poseidon/cairo0_fibonacci.cairo create mode 100644 examples/proofs/small/cairo0_fibonacci.cairo create mode 100644 examples/proofs/starknet/cairo0_fibonacci.cairo create mode 100644 examples/proofs/starknet_with_keccak/cairo0_fibonacci.cairo diff --git a/examples/proofs/cpu_air_params.json b/examples/proofs/cpu_air_params.json new file mode 100644 index 000000000..475e8f1b6 --- /dev/null +++ b/examples/proofs/cpu_air_params.json @@ -0,0 +1,28 @@ +{ + "field": "PrimeField0", + "channel_hash": "poseidon3", + "commitment_hash": "keccak256_masked160_lsb", + "n_verifier_friendly_commitment_layers": 1000, + "pow_hash": "keccak256", + "statement": { + "page_hash": "pedersen" + }, + "stark": { + "fri": { + "fri_step_list": [ + 0, + 4, + 4, + 2 + ], + "last_layer_degree_bound": 128, + "n_queries": 18, + "proof_of_work_bits": 24 + }, + "log_n_cosets": 2 + }, + + "use_extension_field": false, + "verifier_friendly_channel_updates": true, + "verifier_friendly_commitment_hash": "poseidon3" +} \ No newline at end of file diff --git a/examples/proofs/cpu_air_prover_config.json b/examples/proofs/cpu_air_prover_config.json new file mode 100644 index 000000000..d7465eaf6 --- /dev/null +++ b/examples/proofs/cpu_air_prover_config.json @@ -0,0 +1,9 @@ +{ + "cached_lde_config": { + "store_full_lde": false, + "use_fft_for_eval": false + }, + "constraint_polynomial_task_size": 256, + "n_out_of_memory_merkle_layers": 0, + "table_prover_n_tasks_per_segment": 32 +} diff --git a/examples/proofs/dex/cairo0_fibonacci.cairo b/examples/proofs/dex/cairo0_fibonacci.cairo new file mode 100644 index 000000000..9b789d4ab --- /dev/null +++ b/examples/proofs/dex/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check ecdsa +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, ecdsa_ptr=ecdsa_ptr + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file diff --git a/examples/proofs/fibonacci_input.json b/examples/proofs/fibonacci_input.json new file mode 100644 index 000000000..4c9a1f982 --- /dev/null +++ b/examples/proofs/fibonacci_input.json @@ -0,0 +1,3 @@ +{ + "fibonacci_claim_index": 10000 +} diff --git a/examples/proofs/generate,py b/examples/proofs/generate,py new file mode 100644 index 000000000..8d1e57b97 --- /dev/null +++ b/examples/proofs/generate,py @@ -0,0 +1,153 @@ +import os +import subprocess +import tempfile +import logging +import json +from math import ceil, log + +# Setup logging configuration +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +# List of layouts to process +LAYOUTS = ['dex', 'recursive', 'recursive_with_poseidon', 'small', 'starknet', 'starknet_with_keccak'] +# LAYOUTS = ['dynamic'] + +# Paths for required files +PARAMETER_FILE = 'cpu_air_params.json' +PROVER_CONFIG_FILE = 'cpu_air_prover_config.json' +PROGRAM_INPUT_FILE = 'fibonacci_input.json' + +def run_command(command: list): + """Run a shell command and log the output or errors.""" + try: + logging.info(f'Running command: {" ".join(command)}') + subprocess.run(command, check=True) + except subprocess.CalledProcessError as e: + logging.error(f"Command failed: {e}") + raise + +def extract_steps(public_input_file: str) -> int: + """Extract 'n_steps' from the public input JSON file.""" + with open(public_input_file, 'r') as f: + public_input = json.load(f) + return public_input.get("n_steps", 0) + +def compute_fri_step_list(n_steps: int, config: dict) -> list: + """Compute a new 'fri_step_list' based on the provided n_steps and config template.""" + n_steps_log = ceil(log(n_steps, 2)) + last_layer_degree_bound_log = ceil(log(config["stark"]["fri"]["last_layer_degree_bound"], 2)) + sigma_fri_step_list = n_steps_log + 4 - last_layer_degree_bound_log + + q, r = divmod(sigma_fri_step_list, 4) + return [0] + [4] * q + ([r] if r > 0 else []) + +def update_parameter_file(parameter_file_path: str, tmpdir: str, n_steps: int) -> str: + """Update the parameter file with a new 'fri_step_list' and save to a temporary file.""" + with open(parameter_file_path, 'r') as f: + config = json.load(f) + + # Update fri_step_list + config["stark"]["fri"]["fri_step_list"] = compute_fri_step_list(n_steps, config) + + # Save updated config to a temporary file + updated_file = os.path.join(tmpdir, 'updated_cpu_air_params.json') + with open(updated_file, 'w') as f: + json.dump(config, f, indent=4) + + logging.info(f"Updated parameter file saved: {updated_file}") + return updated_file + +def build_cairo_run_command(layout: str, compiled_output: str, trace_file: str, memory_file: str, + public_input_file: str, private_input_file: str) -> list: + """Build the cairo-run command with optional parameters based on the layout.""" + base_command = [ + 'cairo-run', + '--program', compiled_output, + '--layout', layout, + '--proof_mode', + '--program_input', PROGRAM_INPUT_FILE, + '--trace_file', trace_file, + '--memory_file', memory_file, + '--air_private_input', private_input_file, + '--air_public_input', public_input_file, + '--print_info', + '--print_output' + ] + + # Add dynamic layout-specific parameter + if layout == 'dynamic': + cairo_layout_params_file = os.path.join(layout, 'cairo_layout_params.json') + base_command.extend(['--cairo_layout_params_file', cairo_layout_params_file]) + + return base_command + +def process_layout(layout: str): + """Main process for compiling, running, and proving for a given layout.""" + logging.info(f"Processing layout: {layout}") + + with tempfile.TemporaryDirectory() as tmpdir: + # Compile the Cairo program + compiled_output = os.path.join(tmpdir, 'fibonacci_compiled.json') + run_command([ + 'cairo-compile', + f'{layout}/cairo0_fibonacci.cairo', + '--output', compiled_output, + '--no_debug_info', + '--proof_mode' + ]) + + # Prepare files for the run step + trace_file = os.path.join(tmpdir, 'fibonacci_trace.bin') + memory_file = os.path.join(tmpdir, 'fibonacci_memory.bin') + public_input_file = os.path.join(tmpdir, 'fibonacci_public_input.json') + private_input_file = os.path.join(tmpdir, 'fibonacci_private_input.json') + + # Build and run the Cairo program command + cairo_run_command = [ + 'cairo-run', + '--program', compiled_output, + '--layout', layout, + '--proof_mode', + '--program_input', PROGRAM_INPUT_FILE, + '--trace_file', trace_file, + '--memory_file', memory_file, + '--air_private_input', private_input_file, + '--air_public_input', public_input_file, + '--print_info', + '--print_output' + ] + + # Add dynamic layout-specific parameter + if layout == 'dynamic': + cairo_layout_params_file = os.path.join(layout, 'cairo_layout_params.json') + cairo_run_command.extend(['--cairo_layout_params_file', cairo_layout_params_file]) + + run_command(cairo_run_command) + + # Update parameter file with new fri_step_list + n_steps = extract_steps(public_input_file) + updated_parameter_file = update_parameter_file(PARAMETER_FILE, tmpdir, n_steps) + + # Run the prover + proof_output = f'{layout}/cairo0_stone6_keccak_160_lsb_example_proof.json' + run_command([ + 'cpu_air_prover', + '--parameter_file', updated_parameter_file, + '--prover_config_file', PROVER_CONFIG_FILE, + '--public_input_file', public_input_file, + '--private_input_file', private_input_file, + '--out_file', proof_output, + '--generate_annotations' + ]) + + logging.info(f"Proof saved for {layout} in {proof_output}") + +# Main execution loop for each layout +for layout in LAYOUTS: + try: + process_layout(layout) + except Exception as e: + logging.error(f"Error processing layout {layout}: {e}") + continue + +logging.info("Process completed for all layouts.") diff --git a/examples/proofs/recursive/cairo0_fibonacci.cairo b/examples/proofs/recursive/cairo0_fibonacci.cairo new file mode 100644 index 000000000..e7d24404b --- /dev/null +++ b/examples/proofs/recursive/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check bitwise +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, bitwise_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, bitwise_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, bitwise_ptr=bitwise_ptr + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file diff --git a/examples/proofs/recursive_with_poseidon/cairo0_fibonacci.cairo b/examples/proofs/recursive_with_poseidon/cairo0_fibonacci.cairo new file mode 100644 index 000000000..bfe91c87a --- /dev/null +++ b/examples/proofs/recursive_with_poseidon/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check bitwise poseidon +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, bitwise_ptr: felt*, poseidon_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, bitwise_ptr: felt*, poseidon_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, bitwise_ptr=bitwise_ptr, poseidon_ptr=poseidon_ptr + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file diff --git a/examples/proofs/small/cairo0_fibonacci.cairo b/examples/proofs/small/cairo0_fibonacci.cairo new file mode 100644 index 000000000..9b789d4ab --- /dev/null +++ b/examples/proofs/small/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check ecdsa +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, ecdsa_ptr=ecdsa_ptr + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file diff --git a/examples/proofs/starknet/cairo0_fibonacci.cairo b/examples/proofs/starknet/cairo0_fibonacci.cairo new file mode 100644 index 000000000..7c0704a4f --- /dev/null +++ b/examples/proofs/starknet/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check ecdsa bitwise ec_op poseidon +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*, bitwise_ptr: felt*, ec_op_ptr: felt*, poseidon_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*, bitwise_ptr: felt*, ec_op_ptr: felt*, poseidon_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, ecdsa_ptr=ecdsa_ptr, bitwise_ptr=bitwise_ptr, ec_op_ptr=ec_op_ptr, poseidon_ptr=poseidon_ptr + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file diff --git a/examples/proofs/starknet_with_keccak/cairo0_fibonacci.cairo b/examples/proofs/starknet_with_keccak/cairo0_fibonacci.cairo new file mode 100644 index 000000000..8e14ec5ad --- /dev/null +++ b/examples/proofs/starknet_with_keccak/cairo0_fibonacci.cairo @@ -0,0 +1,44 @@ +// Copyright 2023 StarkWare Industries Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.starkware.co/open-source-license/ +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions +// and limitations under the License. + +%builtins output pedersen range_check ecdsa bitwise ec_op keccak poseidon +func main( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*, bitwise_ptr: felt*, ec_op_ptr: felt*, keccak_ptr: felt*, poseidon_ptr: felt*) -> ( + output_ptr: felt*, pedersen_ptr: felt*, range_check_ptr: felt*, ecdsa_ptr: felt*, bitwise_ptr: felt*, ec_op_ptr: felt*, keccak_ptr: felt*, poseidon_ptr: felt* + ) { + alloc_locals; + + // Load fibonacci_claim_index and copy it to the output segment. + local fibonacci_claim_index; + %{ ids.fibonacci_claim_index = program_input['fibonacci_claim_index'] %} + + assert output_ptr[0] = fibonacci_claim_index; + let res = fib(1, 1, fibonacci_claim_index); + assert output_ptr[1] = res; + + // Return the updated output_ptr. + return ( + output_ptr=&output_ptr[2], pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr, ecdsa_ptr=ecdsa_ptr, bitwise_ptr=bitwise_ptr, ec_op_ptr=ec_op_ptr, keccak_ptr=keccak_ptr, poseidon_ptr=poseidon_ptr, + ); +} + +func fib(first_element: felt, second_element: felt, n: felt) -> felt { + if (n == 0) { + return second_element; + } + + return fib( + first_element=second_element, second_element=first_element + second_element, n=n - 1 + ); +} \ No newline at end of file