Skip to content

Commit 61371fd

Browse files
Improve sierra2casm-dbg (#1206)
* Add sierra2casm-dbg * Sync cairo version between sierra2casm-dbg and root * Bump Cairo VM version in sierra2casm-dbg * Fix compilation and linter errors * Bump Cairo in sierra2casm-dbg * Remove unused serde dep in sierra2casm-dbg * Remove Rust toolchain in sierra2casm-dbg * Add sierra2casm-dbg CI job (#1201) * Move cairo-lang dependencies to workspace * Remove sierra-emu/.gitignore * Update lock * Add fibonacci.cairo example for sierra emulator * Simplify Makefile * Simplify README and improve documentation on how to use the binary * Add make check * Improve examples * Document make check * Remove unused script * Add fibonacci_contract.cairo * Fix typo in Makefile * Fix CI * Use cairo2/corelib instead of corelib for symlinking in sierra emu * Improve Sierra Emulator descritopn * Move more dependencies to workspace * Rename to casm-data-flow * Add Makefile * Add basic run-contract example * Add fibonacci_starknet.cairo * Fix hint format * Add basic README.md * Update dependencies * Print gas usage * Finish README.md * Add .PHONY * Fix paragraph * Move deps to workspace * Fix whitespace * Fix whitespace * Fix README.md --------- Co-authored-by: gabrielbosio <gabrielbosio95@gmail.com> Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com>
1 parent d75ca83 commit 61371fd

File tree

18 files changed

+338
-69
lines changed

18 files changed

+338
-69
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ jobs:
375375
- name: Retreive cached dependecies
376376
uses: Swatinem/rust-cache@v2
377377
- name: Build
378-
working-directory: ./debug_utils/sierra2casm-dbg
378+
working-directory: ./debug_utils/casm-data-flow
379379
run: cargo build --all-features --verbose
380380
- name: Run tests
381-
working-directory: ./debug_utils/sierra2casm-dbg
381+
working-directory: ./debug_utils/casm-data-flow
382382
run: cargo test

Cargo.lock

Lines changed: 50 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,10 @@ name = "libfuncs"
179179
harness = false
180180

181181
[workspace]
182-
members = ["debug_utils/sierra-emu", "debug_utils/sierra2casm-dbg"]
182+
members = ["debug_utils/sierra-emu", "debug_utils/casm-data-flow"]
183183

184184
[workspace.dependencies]
185+
cairo-lang-casm = "=2.12.0-dev.1"
185186
cairo-lang-compiler = "=2.12.0-dev.1"
186187
cairo-lang-defs = "=2.12.0-dev.1"
187188
cairo-lang-filesystem = "=2.12.0-dev.1"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "casm-data-flow"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
bincode = { version = "2.0.0-rc.3", default-features = false }
8+
clap = { version = "4.5.27", features = ["derive"] }
9+
serde_json = "1.0.138"
10+
starknet-types-core.workspace = true
11+
cairo-lang-casm = { workspace = true, features = [ "serde", ] }
12+
cairo-lang-utils.workspace = true
13+
cairo-lang-starknet-classes.workspace = true
14+
cairo-vm = { git = "https://github.com/lambdaclass/cairo-vm/", rev = "3b36cd92f68f3dc26ddf5aba6c1f9a50ff3d303f", features = ["cairo-1-hints"] }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
usage:
2+
@echo "Usage:"
3+
@echo " build: Builds casm-data-flow."
4+
@echo " check: Checks format and lints."
5+
@echo " clean: Cleans the built artifacts."
6+
.PHONY: usage
7+
8+
build:
9+
cargo build --release --all-features
10+
.PHONY: build
11+
12+
check:
13+
cargo fmt --all -- --check
14+
cargo clippy --all-targets --all-features -- -D warnings
15+
.PHONY: check
16+
17+
clean:
18+
cargo clean
19+
.PHONY: clean
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Casm Data Flow
2+
3+
A data flow analyzer for a Cairo VM. Currently, it only supports starknet contracts.
4+
5+
It is useful when trying to debug a gas difference between Cairo Native and Cairo VM.
6+
7+
## Usage
8+
9+
First, we need to compile the contract:
10+
11+
```bash
12+
../../cairo2/bin/starknet-compile -s programs/fibonacci_starknet.cairo > programs/fibonacci_starknet.sierra.json
13+
../../cairo2/bin/starknet-sierra-compile programs/fibonacci_starknet.sierra.json programs/fibonacci_starknet.casm.json
14+
```
15+
16+
Then, we execute the contract. In this example, we are using [our Cairo VM](https://github.com/lambdaclass/cairo-vm).
17+
18+
```bash
19+
cargo run --example run-contract -- programs/fibonacci_starknet.casm.json programs/fibonacci_starknet.memory programs/fibonacci_starknet.trace
20+
```
21+
22+
The example prints the starting and final gas:
23+
24+
```
25+
Starting Gas: 18446744073709551615
26+
Final Gas: 18446744073709544205
27+
```
28+
29+
We will need the trace and memory files generated, to find a path from the starting gas to the final gas.
30+
31+
```bash
32+
cargo run -- --program-path programs/fibonacci_starknet.casm.json --trace-path programs/fibonacci_starknet.trace --memory-path programs/fibonacci_starknet.memory -s 18446744073709551615 -t 18446744073709544205
33+
```
34+
35+
The binary prints the full path from the starting gas to the final gas.
36+
37+
```
38+
[184] = 18446744073709551615
39+
[212] = 18446744073709550345 (Δ-1270)
40+
[222] = 18446744073709549075 (Δ-1270)
41+
[232] = 18446744073709547805 (Δ-1270)
42+
[242] = 18446744073709546535 (Δ-1270)
43+
[252] = 18446744073709545265 (Δ-1270)
44+
[262] = 18446744073709543995 (Δ-1270)
45+
[272] = 18446744073709542725 (Δ-1270)
46+
[282] = 18446744073709541455 (Δ-1270)
47+
[292] = 18446744073709540185 (Δ-1270)
48+
[302] = 18446744073709538915 (Δ-1270)
49+
[312] = 18446744073709537645 (Δ-1270)
50+
[315] = 18446744073709539715 (Δ2070)
51+
[321] = 18446744073709544205 (Δ4490)
52+
```

debug_utils/sierra2casm-dbg/examples/basic.rs renamed to debug_utils/casm-data-flow/examples/basic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use bincode::de::read::SliceReader;
2-
use sierra2casm_dbg::{decode_instruction, GraphMappings, Memory, Trace, ValueId};
2+
use casm_data_flow::{decode_instruction, GraphMappings, Memory, Trace, ValueId};
33
use std::{collections::HashMap, fs};
44

55
fn main() {
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
use std::{fs::File, io::Write, path::PathBuf};
2+
3+
use bincode::enc::write::Writer;
4+
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
5+
use cairo_vm::{
6+
cairo_run::{write_encoded_memory, write_encoded_trace},
7+
hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor,
8+
types::{
9+
builtin_name::BuiltinName, layout_name::LayoutName, program::Program,
10+
relocatable::MaybeRelocatable,
11+
},
12+
vm::runners::cairo_runner::{CairoArg, CairoRunner, RunResources},
13+
};
14+
use clap::Parser;
15+
use starknet_types_core::felt::Felt;
16+
17+
#[derive(Debug, Parser)]
18+
struct Args {
19+
contract_path: PathBuf,
20+
memory_path: PathBuf,
21+
trace_path: PathBuf,
22+
}
23+
24+
pub fn main() {
25+
let cli_args = Args::parse();
26+
let calldata_args = [MaybeRelocatable::from(10)];
27+
let expected_retdata = [Felt::from(89)];
28+
29+
let contract_file = File::open(cli_args.contract_path).expect("failed to open contract path");
30+
let contract: CasmContractClass =
31+
serde_json::from_reader(contract_file).expect("failed to parse contract file");
32+
33+
let program = Program::try_from(contract.clone())
34+
.expect("failed to build vm program from contract class");
35+
36+
let mut runner =
37+
CairoRunner::new(&program, LayoutName::all_cairo, None, false, true, false).unwrap();
38+
39+
let program_builtins = contract
40+
.entry_points_by_type
41+
.external
42+
.iter()
43+
.find(|e| e.offset == 0)
44+
.unwrap()
45+
.builtins
46+
.iter()
47+
.map(|s| BuiltinName::from_str(s).expect("Invalid builtin name"))
48+
.collect::<Vec<_>>();
49+
runner
50+
.initialize_function_runner_cairo_1(&program_builtins)
51+
.unwrap();
52+
53+
let syscall_segment = MaybeRelocatable::from(runner.vm.add_memory_segment());
54+
55+
let builtins = runner.get_program_builtins();
56+
57+
let builtin_segment: Vec<MaybeRelocatable> = runner
58+
.vm
59+
.get_builtin_runners()
60+
.iter()
61+
.filter(|b| builtins.contains(&b.name()))
62+
.flat_map(|b| b.initial_stack())
63+
.collect();
64+
65+
let initial_gas = MaybeRelocatable::from(usize::MAX);
66+
println!("Starting Gas: {}", &initial_gas);
67+
68+
let mut implicit_args = builtin_segment;
69+
implicit_args.extend([initial_gas]);
70+
implicit_args.extend([syscall_segment]);
71+
72+
let builtin_costs: Vec<MaybeRelocatable> =
73+
vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()];
74+
let builtin_costs_ptr = runner.vm.add_memory_segment();
75+
runner
76+
.vm
77+
.load_data(builtin_costs_ptr, &builtin_costs)
78+
.unwrap();
79+
80+
let core_program_end_ptr =
81+
(runner.program_base.unwrap() + runner.get_program().data_len()).unwrap();
82+
let program_extra_data: Vec<MaybeRelocatable> =
83+
vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()];
84+
runner
85+
.vm
86+
.load_data(core_program_end_ptr, &program_extra_data)
87+
.unwrap();
88+
89+
let calldata_start = runner.vm.add_memory_segment();
90+
let calldata_end = runner.vm.load_data(calldata_start, &calldata_args).unwrap();
91+
92+
let mut entrypoint_args: Vec<CairoArg> = implicit_args
93+
.iter()
94+
.map(|m| CairoArg::from(m.clone()))
95+
.collect();
96+
entrypoint_args.extend([
97+
MaybeRelocatable::from(calldata_start).into(),
98+
MaybeRelocatable::from(calldata_end).into(),
99+
]);
100+
let entrypoint_args: Vec<&CairoArg> = entrypoint_args.iter().collect();
101+
102+
let mut hint_processor =
103+
Cairo1HintProcessor::new(&contract.hints, RunResources::new(621), false);
104+
105+
runner
106+
.run_from_entrypoint(
107+
0,
108+
&entrypoint_args,
109+
true,
110+
Some(runner.get_program().data_len() + program_extra_data.len()),
111+
&mut hint_processor,
112+
)
113+
.expect("failed to execute contract");
114+
115+
let return_values = runner.vm.get_return_values(5).unwrap();
116+
let final_gas = return_values[0].get_int().unwrap();
117+
let retdata_start = return_values[3].get_relocatable().unwrap();
118+
let retdata_end = return_values[4].get_relocatable().unwrap();
119+
let retdata: Vec<Felt> = runner
120+
.vm
121+
.get_integer_range(retdata_start, (retdata_end - retdata_start).unwrap())
122+
.unwrap()
123+
.iter()
124+
.map(|c| c.clone().into_owned())
125+
.collect();
126+
127+
println!("Final Gas: {}", final_gas);
128+
129+
assert_eq!(retdata, expected_retdata);
130+
131+
runner.relocate(true).expect("failed to relocate trace");
132+
133+
let trace_file = File::create(cli_args.trace_path).expect("failed to create trace file");
134+
let mut trace_writer = FileWriter::new(trace_file);
135+
write_encoded_trace(
136+
&runner.relocated_trace.expect("trace should exist"),
137+
&mut trace_writer,
138+
)
139+
.expect("failed to write trace");
140+
141+
let memory_file = File::create(cli_args.memory_path).expect("failed to create memory file");
142+
let mut memory_writer = FileWriter::new(memory_file);
143+
write_encoded_memory(&runner.relocated_memory, &mut memory_writer)
144+
.expect("failed to write memory");
145+
}
146+
147+
struct FileWriter {
148+
buf_writer: File,
149+
bytes_written: usize,
150+
}
151+
152+
impl Writer for FileWriter {
153+
fn write(&mut self, bytes: &[u8]) -> Result<(), bincode::error::EncodeError> {
154+
self.buf_writer
155+
.write_all(bytes)
156+
.map_err(|e| bincode::error::EncodeError::Io {
157+
inner: e,
158+
index: self.bytes_written,
159+
})?;
160+
161+
self.bytes_written += bytes.len();
162+
163+
Ok(())
164+
}
165+
}
166+
167+
impl FileWriter {
168+
fn new(buf_writer: File) -> Self {
169+
Self {
170+
buf_writer,
171+
bytes_written: 0,
172+
}
173+
}
174+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#[starknet::contract]
2+
mod Fibonacci {
3+
#[storage]
4+
struct Storage { }
5+
6+
#[external(v0)]
7+
fn fibonacci(ref self: ContractState, value: felt252) -> felt252 {
8+
return super::fibonacci(1, 1, value);
9+
}
10+
}
11+
12+
fn fibonacci(a: felt252, b: felt252, n: felt252) -> felt252 {
13+
match n {
14+
0 => a,
15+
_ => fibonacci(b, a + b, n - 1),
16+
}
17+
}
File renamed without changes.

0 commit comments

Comments
 (0)