Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement air_private_input #1552

Merged
merged 36 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fe145e8
Implement get_air_private_input for RangeCheck;
fmoletta Jan 9, 2024
dff4d39
Implement air_private_input for Bitwise;
fmoletta Jan 10, 2024
c6b85fd
Implement air_private_input for Hash
fmoletta Jan 10, 2024
5ee533a
Update proof_programs symlinks
fmoletta Jan 10, 2024
b32f9dc
Add EcOp priv input variant
fmoletta Jan 10, 2024
aa1d4f1
Implement air_private_input for EcOp
fmoletta Jan 10, 2024
548bbaa
Implement air_private_input for Poseidon & Signature
fmoletta Jan 10, 2024
cca1f55
Implement air_private_input for Keccak
fmoletta Jan 10, 2024
df18495
Add AirPrivateInput serialization
fmoletta Jan 10, 2024
fd26554
Remove unwrap
fmoletta Jan 10, 2024
8efc27b
Add targets to compare private inputs against python vm
fmoletta Jan 10, 2024
b6228c4
Add separate script to compare private inputs
fmoletta Jan 11, 2024
4a32062
Ignore & Clean output files
fmoletta Jan 11, 2024
b2ba10b
Fix target
fmoletta Jan 11, 2024
e91b523
Fix + fmt
fmoletta Jan 11, 2024
93ee579
Fetch absolute paths in cli and remove feature-gate
fmoletta Jan 11, 2024
a0f2eb7
Fix ecdsa private input
fmoletta Jan 11, 2024
c92928f
Add no-std import
fmoletta Jan 11, 2024
9770597
Add Chaneglog entry
fmoletta Jan 11, 2024
f2b19a1
Update README
fmoletta Jan 11, 2024
ff44b02
Add cli tests
fmoletta Jan 11, 2024
912bda9
Add case to cli test
fmoletta Jan 11, 2024
ebc249e
Fix conditional
fmoletta Jan 11, 2024
1c77bd4
Add no-std import
fmoletta Jan 11, 2024
4bcc3e3
fmt
fmoletta Jan 11, 2024
37434aa
fix
fmoletta Jan 11, 2024
b6b18fe
Remove unwraps
fmoletta Jan 11, 2024
783b333
Add tests so coverage doesnt sink
fmoletta Jan 11, 2024
2a5bed1
Fix test
fmoletta Jan 11, 2024
95ec39f
Fix test
fmoletta Jan 11, 2024
614938f
Fix test
fmoletta Jan 11, 2024
fe33a2b
Fix symlink
fmoletta Jan 11, 2024
4a71f3c
Remove broken file
fmoletta Jan 11, 2024
b6bdabb
Merge branch 'update-symlinks' into air_private_input
fmoletta Jan 11, 2024
921b841
Merge branch 'main' into air_private_input
Oppen Jan 15, 2024
b20da7d
Merge branch 'main' into air_private_input
fmoletta Jan 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
**/*.trace
**/*.memory
**/*.air_public_input
**/*.air_private_input
**/*.swp
bench/results
.python-version
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: Implement air_private_input [#1552](https://github.com/lambdaclass/cairo-vm/pull/1552)

* feat: Add `proof_mode` flag to `cairo1-run` [#1537] (https://github.com/lambdaclass/cairo-vm/pull/1537)
* The cairo1-run crate no longer compiles and executes in proof_mode by default
* Add flag `proof_mode` to cairo1-run crate. Activating this flag will enable proof_mode compilation and execution
Expand Down
20 changes: 13 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ endif
deps deps-macos cargo-deps build run check test clippy coverage benchmark \
compare_benchmarks_deps compare_benchmarks docs clean \
compare_vm_output compare_trace_memory compare_trace compare_memory \
compare_trace_memory_proof compare_all_proof compare_trace_proof compare_memory_proof compare_air_public_input \
compare_trace_memory_proof compare_all_proof compare_trace_proof compare_memory_proof compare_air_public_input compare_air_private_input\
cairo_bench_programs cairo_proof_programs cairo_test_programs cairo_1_test_contracts cairo_2_test_contracts \
cairo_trace cairo-vm_trace cairo_proof_trace cairo-vm_proof_trace \
fuzzer-deps fuzzer-run-cairo-compiled fuzzer-run-hint-diff build-cairo-lang hint-accountant \
Expand All @@ -37,10 +37,12 @@ COMPILED_PROOF_TESTS:=$(patsubst $(TEST_PROOF_DIR)/%.cairo, $(TEST_PROOF_DIR)/%.
CAIRO_MEM_PROOF:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.memory, $(COMPILED_PROOF_TESTS))
CAIRO_TRACE_PROOF:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.trace, $(COMPILED_PROOF_TESTS))
CAIRO_AIR_PUBLIC_INPUT:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.air_public_input, $(COMPILED_PROOF_TESTS))
CAIRO_AIR_PRIVATE_INPUT:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.air_private_input, $(COMPILED_PROOF_TESTS))

CAIRO_RS_MEM_PROOF:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.rs.memory, $(COMPILED_PROOF_TESTS))
CAIRO_RS_TRACE_PROOF:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.rs.trace, $(COMPILED_PROOF_TESTS))
CAIRO_RS_AIR_PUBLIC_INPUT:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.rs.air_public_input, $(COMPILED_PROOF_TESTS))
CAIRO_RS_AIR_PRIVATE_INPUT:=$(patsubst $(TEST_PROOF_DIR)/%.json, $(TEST_PROOF_DIR)/%.rs.air_private_input, $(COMPILED_PROOF_TESTS))

PROOF_BENCH_DIR=cairo_programs/benchmarks
PROOF_BENCH_FILES:=$(wildcard $(PROOF_BENCH_DIR)/*.cairo)
Expand All @@ -49,11 +51,11 @@ PROOF_COMPILED_BENCHES:=$(patsubst $(PROOF_BENCH_DIR)/%.cairo, $(PROOF_BENCH_DIR
$(TEST_PROOF_DIR)/%.json: $(TEST_PROOF_DIR)/%.cairo
cairo-compile --cairo_path="$(TEST_PROOF_DIR):$(PROOF_BENCH_DIR)" $< --output $@ --proof_mode

$(TEST_PROOF_DIR)/%.rs.trace $(TEST_PROOF_DIR)/%.rs.memory $(TEST_PROOF_DIR)/%.rs.air_public_input: $(TEST_PROOF_DIR)/%.json $(RELBIN)
cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout starknet_with_keccak --proof_mode $< --trace_file $@ --memory_file $(@D)/$(*F).rs.memory --air_public_input $(@D)/$(*F).rs.air_public_input
$(TEST_PROOF_DIR)/%.rs.trace $(TEST_PROOF_DIR)/%.rs.memory $(TEST_PROOF_DIR)/%.rs.air_public_input $(TEST_PROOF_DIR)/%.rs.air_private_input: $(TEST_PROOF_DIR)/%.json $(RELBIN)
cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout starknet_with_keccak --proof_mode $< --trace_file $(@D)/$(*F).rs.trace --memory_file $(@D)/$(*F).rs.memory --air_public_input $(@D)/$(*F).rs.air_public_input --air_private_input $(@D)/$(*F).rs.air_private_input

$(TEST_PROOF_DIR)/%.trace $(TEST_PROOF_DIR)/%.memory $(TEST_PROOF_DIR)/%.air_public_input: $(TEST_PROOF_DIR)/%.json
cairo-run --layout starknet_with_keccak --proof_mode --program $< --trace_file $(@D)/$(*F).trace --air_public_input $(@D)/$(*F).air_public_input --memory_file $(@D)/$(*F).memory
$(TEST_PROOF_DIR)/%.trace $(TEST_PROOF_DIR)/%.memory $(TEST_PROOF_DIR)/%.air_public_input $(TEST_PROOF_DIR)/%.air_private_input: $(TEST_PROOF_DIR)/%.json
cairo-run --layout starknet_with_keccak --proof_mode --program $< --trace_file $(@D)/$(*F).trace --air_public_input $(@D)/$(*F).air_public_input --memory_file $(@D)/$(*F).memory --air_private_input $(@D)/$(*F).air_private_input

$(PROOF_BENCH_DIR)/%.json: $(PROOF_BENCH_DIR)/%.cairo
cairo-compile --cairo_path="$(TEST_PROOF_DIR):$(PROOF_BENCH_DIR)" $< --output $@ --proof_mode
Expand Down Expand Up @@ -289,8 +291,8 @@ compare_memory: $(CAIRO_RS_MEM) $(CAIRO_MEM)
compare_trace_memory_proof: $(COMPILED_PROOF_TESTS) $(CAIRO_RS_TRACE_PROOF) $(CAIRO_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) $(CAIRO_MEM_PROOF)
cd vm/src/tests; ./compare_vm_state.sh trace memory proof_mode

compare_all_proof: $(COMPILED_PROOF_TESTS) $(CAIRO_RS_TRACE_PROOF) $(CAIRO_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) $(CAIRO_MEM_PROOF) $(CAIRO_RS_AIR_PUBLIC_INPUT) $(CAIRO_AIR_PUBLIC_INPUT)
cd vm/src/tests; ./compare_vm_state.sh trace memory proof_mode air_public_input
compare_all_proof: $(COMPILED_PROOF_TESTS) $(CAIRO_RS_TRACE_PROOF) $(CAIRO_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) $(CAIRO_MEM_PROOF) $(CAIRO_RS_AIR_PUBLIC_INPUT) $(CAIRO_AIR_PUBLIC_INPUT) $(CAIRO_RS_AIR_PRIVATE_INPUT) $(CAIRO_AIR_PRIVATE_INPUT)
cd vm/src/tests; ./compare_vm_state.sh trace memory proof_mode air_public_input air_private_input

compare_trace_proof: $(CAIRO_RS_TRACE_PROOF) $(CAIRO_TRACE_PROOF)
cd vm/src/tests; ./compare_vm_state.sh trace proof_mode
Expand All @@ -301,6 +303,9 @@ compare_memory_proof: $(CAIRO_RS_MEM_PROOF) $(CAIRO_MEM_PROOF)
compare_air_public_input: $(CAIRO_RS_AIR_PUBLIC_INPUT) $(CAIRO_AIR_PUBLIC_INPUT)
cd vm/src/tests; ./compare_vm_state.sh memory proof_mode air_public_input

compare_air_private_input: $(CAIRO_RS_AIR_PRIVATE_INPUT) $(CAIRO_AIR_PRIVATE_INPUT)
cd vm/src/tests; ./compare_vm_state.sh memory proof_mode air_private_input

# Run with nightly enable the `doc_cfg` feature wich let us provide clear explaination about which parts of the code are behind a feature flag
docs:
RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --verbose --release --locked --no-deps --all-features --open
Expand All @@ -318,6 +323,7 @@ clean:
rm -f $(TEST_PROOF_DIR)/*.memory
rm -f $(TEST_PROOF_DIR)/*.trace
rm -f $(TEST_PROOF_DIR)/*.air_public_input
rm -f $(TEST_PROOF_DIR)/*.air_private_input
rm -rf cairo-vm-env
rm -rf cairo-vm-pypy-env
rm -rf cairo
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ The cairo-vm-cli supports the following optional arguments:

- `--air_public_input <AIR_PUBLIC_INPUT>`: Receives the name of a file and outputs the AIR public inputs into it. Can only be used if proof_mode is also enabled.

- `--air_private_input <AIR_PRIVATE_INPUT>`: Receives the name of a file and outputs the AIR private inputs into it. Can only be used if proof_mode, trace_file & memory_file are also enabled.

For example, to obtain the air public inputs from a fibonacci program run, we can run :

```bash
Expand Down
89 changes: 82 additions & 7 deletions cairo-vm-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct Args {
secure_run: Option<bool>,
#[clap(long = "air_public_input")]
air_public_input: Option<String>,
#[clap(long = "air_private_input")]
air_private_input: Option<String>,
}

fn validate_layout(value: &str) -> Result<String, String> {
Expand Down Expand Up @@ -119,6 +121,30 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> {
return Err(Error::Cli(error));
}

if args.air_private_input.is_some() && !args.proof_mode {
let error = Args::command().error(
clap::error::ErrorKind::ArgumentConflict,
"--air_private_input can only be used in proof_mode.",
);
return Err(Error::Cli(error));
}

if args.air_private_input.is_some() && args.trace_file.is_none() {
let error = Args::command().error(
clap::error::ErrorKind::ArgumentConflict,
"--trace_file must be set when --air_private_input is set.",
);
return Err(Error::Cli(error));
}

if args.air_private_input.is_some() && args.memory_file.is_none() {
let error = Args::command().error(
clap::error::ErrorKind::ArgumentConflict,
"--memory_file must be set when --air_private_input is set.",
);
return Err(Error::Cli(error));
}

let trace_enabled = args.trace_file.is_some() || args.air_public_input.is_some();
let mut hint_executor = BuiltinHintProcessor::new_empty();
let cairo_run_config = cairo_run::CairoRunConfig {
Expand Down Expand Up @@ -148,7 +174,7 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> {
print!("{output_buffer}");
}

if let Some(trace_path) = args.trace_file {
if let Some(ref trace_path) = args.trace_file {
let relocated_trace = cairo_runner
.relocated_trace
.as_ref()
Expand All @@ -162,7 +188,7 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> {
trace_writer.flush()?;
}

if let Some(memory_path) = args.memory_file {
if let Some(ref memory_path) = args.memory_file {
let memory_file = std::fs::File::create(memory_path)?;
let mut memory_writer =
FileWriter::new(io::BufWriter::with_capacity(5 * 1024 * 1024, memory_file));
Expand All @@ -176,6 +202,31 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> {
std::fs::write(file_path, json)?;
}

if let (Some(file_path), Some(ref trace_file), Some(ref memory_file)) =
(args.air_private_input, args.trace_file, args.memory_file)
{
// Get absolute paths of trace_file & memory_file
let trace_path = trace_file
.as_path()
.canonicalize()
.unwrap_or(trace_file.clone())
.to_string_lossy()
.to_string();
let memory_path = memory_file
.as_path()
.canonicalize()
.unwrap_or(memory_file.clone())
.to_string_lossy()
.to_string();

let json = cairo_runner
.get_air_private_input(&vm)
.to_serializable(trace_path, memory_path)
.serialize_json()
.map_err(PublicInputError::Serde)?;
std::fs::write(file_path, json)?;
}

Ok(())
}

Expand Down Expand Up @@ -212,6 +263,27 @@ mod tests {
assert_matches!(run(args), Err(Error::Cli(_)));
}

#[rstest]
#[case(["cairo-vm-cli", "../cairo_programs/fibonacci.json", "--air_private_input", "/dev/null", "--proof_mode", "--memory_file", "/dev/null"].as_slice())]
fn test_run_air_private_input_no_trace(#[case] args: &[&str]) {
let args = args.iter().cloned().map(String::from);
assert_matches!(run(args), Err(Error::Cli(_)));
}

#[rstest]
#[case(["cairo-vm-cli", "../cairo_programs/fibonacci.json", "--air_private_input", "/dev/null", "--proof_mode", "--trace_file", "/dev/null"].as_slice())]
fn test_run_air_private_input_no_memory(#[case] args: &[&str]) {
let args = args.iter().cloned().map(String::from);
assert_matches!(run(args), Err(Error::Cli(_)));
}

#[rstest]
#[case(["cairo-vm-cli", "../cairo_programs/fibonacci.json", "--air_private_input", "/dev/null", "--trace_file", "/dev/null", "--memory_file", "/dev/null"].as_slice())]
fn test_run_air_private_input_no_proof(#[case] args: &[&str]) {
let args = args.iter().cloned().map(String::from);
assert_matches!(run(args), Err(Error::Cli(_)));
}

#[rstest]
fn test_run_ok(
#[values(None,
Expand All @@ -234,16 +306,17 @@ mod tests {
#[values(false, true)] print_output: bool,
#[values(false, true)] entrypoint: bool,
#[values(false, true)] air_public_input: bool,
#[values(false, true)] air_private_input: bool,
) {
let mut args = vec!["cairo-vm-cli".to_string()];
if let Some(layout) = layout {
args.extend_from_slice(&["--layout".to_string(), layout.to_string()]);
}
if air_public_input {
args.extend_from_slice(&[
"--air_public_input".to_string(),
"air_input.pub".to_string(),
]);
args.extend_from_slice(&["--air_public_input".to_string(), "/dev/null".to_string()]);
}
if air_private_input {
args.extend_from_slice(&["--air_private_input".to_string(), "/dev/null".to_string()]);
}
if proof_mode {
trace_file = true;
Expand All @@ -266,7 +339,9 @@ mod tests {
}

args.push("../cairo_programs/proof_programs/fibonacci.json".to_string());
if air_public_input && !proof_mode {
if air_public_input && !proof_mode
|| (air_private_input && (!proof_mode || !trace_file || !memory_file))
{
assert_matches!(run(args.into_iter()), Err(_));
} else {
assert_matches!(run(args.into_iter()), Ok(_));
Expand Down
2 changes: 1 addition & 1 deletion fuzzer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

142 changes: 142 additions & 0 deletions vm/src/air_private_input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use crate::{
stdlib::{
collections::HashMap,
prelude::{String, Vec},
},
vm::runners::builtin_runner::{
BITWISE_BUILTIN_NAME, EC_OP_BUILTIN_NAME, HASH_BUILTIN_NAME, KECCAK_BUILTIN_NAME,
POSEIDON_BUILTIN_NAME, RANGE_CHECK_BUILTIN_NAME, SIGNATURE_BUILTIN_NAME,
},
};
use serde::{Deserialize, Serialize};

use crate::Felt252;

// Serializable format, matches the file output of the python implementation
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct AirPrivateInputSerializable {
trace_path: String,
memory_path: String,
pedersen: Vec<PrivateInput>,
range_check: Vec<PrivateInput>,
ecdsa: Vec<PrivateInput>,
bitwise: Vec<PrivateInput>,
ec_op: Vec<PrivateInput>,
keccak: Vec<PrivateInput>,
poseidon: Vec<PrivateInput>,
}

// Contains only builtin public inputs, useful for library users
#[derive(Clone, Debug, PartialEq, Eq)]

Check warning on line 30 in vm/src/air_private_input.rs

View check run for this annotation

Codecov / codecov/patch

vm/src/air_private_input.rs#L30

Added line #L30 was not covered by tests
pub struct AirPrivateInput(pub HashMap<&'static str, Vec<PrivateInput>>);

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(untagged)]
pub enum PrivateInput {
Value(PrivateInputValue),
Pair(PrivateInputPair),
EcOp(PrivateInputEcOp),
PoseidonState(PrivateInputPoseidonState),
KeccakState(PrivateInputKeccakState),
Signature(PrivateInputSignature),
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputValue {
pub index: usize,
pub value: Felt252,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputPair {
pub index: usize,
pub x: Felt252,
pub y: Felt252,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputEcOp {
pub index: usize,
pub p_x: Felt252,
pub p_y: Felt252,
pub m: Felt252,
pub q_x: Felt252,
pub q_y: Felt252,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputPoseidonState {
pub index: usize,
pub input_s0: Felt252,
pub input_s1: Felt252,
pub input_s2: Felt252,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputKeccakState {
pub index: usize,
pub input_s0: Felt252,
pub input_s1: Felt252,
pub input_s2: Felt252,
pub input_s3: Felt252,
pub input_s4: Felt252,
pub input_s5: Felt252,
pub input_s6: Felt252,
pub input_s7: Felt252,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrivateInputSignature {
pub index: usize,
pub pubkey: Felt252,
pub msg: Felt252,
pub signature_input: SignatureInput,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct SignatureInput {
pub r: Felt252,
pub w: Felt252,
}

impl AirPrivateInput {
pub fn to_serializable(
&self,
trace_path: String,
memory_path: String,
) -> AirPrivateInputSerializable {
AirPrivateInputSerializable {
trace_path,
memory_path,
pedersen: self.0.get(HASH_BUILTIN_NAME).cloned().unwrap_or_default(),
range_check: self
.0
.get(RANGE_CHECK_BUILTIN_NAME)
.cloned()
.unwrap_or_default(),
ecdsa: self
.0
.get(SIGNATURE_BUILTIN_NAME)
.cloned()
.unwrap_or_default(),
bitwise: self
.0
.get(BITWISE_BUILTIN_NAME)
.cloned()
.unwrap_or_default(),
ec_op: self.0.get(EC_OP_BUILTIN_NAME).cloned().unwrap_or_default(),
keccak: self.0.get(KECCAK_BUILTIN_NAME).cloned().unwrap_or_default(),
poseidon: self
.0
.get(POSEIDON_BUILTIN_NAME)
.cloned()
.unwrap_or_default(),
}
}
}

impl AirPrivateInputSerializable {
pub fn serialize_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(&self)
}
}
Loading
Loading