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

Addition and Addition with Assignment prop tests for felts #718

Merged
merged 21 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

#### Upcoming Changes

* Use CairoArg enum instead of Any in CairoRunner::run_from_entrypoint [#686](https://github.com/lambdaclass/cairo-rs/pull/686)
* Public Api changes:
* Remove `Result` from `MaybeRelocatable::mod_floor`, it now returns a `MaybeRelocatable`
* Add struct `CairoArg`
* Change `arg` argument of `CairoRunner::run_from_entrypoint` from `Vec<&dyn Any>` to `&[&CairoArg]`
* Remove argument `typed_args` from `CairoRunner::run_from_entrypoint`
* Remove no longer used method `gen_typed_arg` from `VirtualMachine` & `MemorySegmentManager`
* Add methods `MemorySegmentManager::gen_cairo_arg` & `MemorySegmentManager::write_simple_args` as typed counterparts to `MemorySegmentManager::gen_arg` & `MemorySegmentManager::write_arg`

#### [0.1.1] - 2023-01-11

* Add input file contents to traceback [#666](https://github.com/lambdaclass/cairo-rs/pull/666/files)
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ description = "Blazing fast Cairo interpreter"
[features]
default = ["with_mimalloc"]
with_mimalloc = ["mimalloc"]
skip_next_instruction_hint = []
# This feature will reference every test-oriented feature.
# Note that these features are not retro-compatible with the cairo Python VM.
test_utils = ["skip_next_instruction_hint"]

[dependencies]
mimalloc = { version = "0.1.29", default-features = false, optional = true }
Expand Down
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ BAD_TEST_DIR=cairo_programs/bad_programs
BAD_TEST_FILES:=$(wildcard $(BAD_TEST_DIR)/*.cairo)
COMPILED_BAD_TESTS:=$(patsubst $(BAD_TEST_DIR)/%.cairo, $(BAD_TEST_DIR)/%.json, $(BAD_TEST_FILES))

JSON_FILES:=$(wildcard $(TEST_DIR)/*.json)
JSON_FILES:=$(filter-out $(TEST_DIR)/*.noretrocompat.*.json, $(JSON_FILES))

$(TEST_DIR)/%.json: $(TEST_DIR)/%.cairo
cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR)" $< --output $@

$(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory: $(TEST_DIR)/%.json build
$(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory: $(JSON_FILES) build
./target/release/cairo-rs-run --layout all $< --trace_file $@ --memory_file $(@D)/$(*F).rs.memory

$(TEST_DIR)/%.trace $(TEST_DIR)/%.memory: $(TEST_DIR)/%.json
$(TEST_DIR)/%.trace $(TEST_DIR)/%.memory: $(JSON_FILES) build
cairo-run --layout all --program $< --trace_file $@ --memory_file $(@D)/$(*F).memory

$(BENCH_DIR)/%.json: $(BENCH_DIR)/%.cairo
Expand Down Expand Up @@ -102,7 +105,7 @@ cairo_trace: $(CAIRO_TRACE) $(CAIRO_MEM)
cairo-rs_trace: $(CAIRO_RS_TRACE) $(CAIRO_RS_MEM)

test: $(COMPILED_PROOF_TESTS) $(COMPILED_TESTS) $(COMPILED_BAD_TESTS)
cargo test --workspace
cargo test --workspace --features test_utils

clippy:
cargo clippy -- -D warnings
Expand Down
90 changes: 66 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,62 @@
- [Possible changes for the future](#possible-changes-for-the-future)
- [Changelog](#changelog)
- [License](#license)


## About
## 🦂 Disclaimer

`cairo-rs` is still being built therefore breaking changes might happen often so use it at your own risks.

## 🐪 About

### This repository
Cairo VM is the virtual machine for the [Cairo language](www.cairo-lang.org/).

There's an older version of [Cairo VM](https://github.com/starkware-libs/cairo-lang) written in Python, which is **currently in production**.

This repository contains the newer version, written in Rust. It's faster and has safer and more expressive typing. Once completed, it will replace the older one as the sole Cairo VM.

cairo-rs is a Rust implementation of the Cairo VM.
### The Cairo language
Cairo is the first production-grade platform for generating [STARK](https://vitalik.ca/general/2017/11/09/starks_part_1.html) proofs for general computation.

The code of the original Cairo VM can be found [here](https://github.com/starkware-libs/cairo-lang).
It's Turing-complete and it was created by [Starkware](https://starkware.co/) as part of the [Starknet](https://starkware.co/starknet/) ecosystem.

## Getting Started
## 🌅 Getting Started

### Dependencies
- [Rust](https://www.rust-lang.org/tools/install)
**Required**
- [Rust 1.66.1](https://www.rust-lang.org/tools/install)
- Cargo
- PyEnv for running the original VM and compiling cairo programs
- cairo-lang (optional)

## Usage
**Optional**

These dependencies are only necessary in order to run the original VM and compile Cairo programs.
- PyEnv with Python 3.9
- cairo-lang

## 🕌 Usage
### Running cairo-rs
Compile with `cargo build --release`, once the binary is built, it can be found in `target/release/` under the name `cairo-rs-run`.
To run a compiled json program through the VM, call the executable giving it the path and name of the file to be executed.
To compile the repository, run:
```bash
cargo build --release
```

Once the binary is built, it can be found in `target/release/` under the name `cairo-rs-run`.

To compile a program, use `cairo-compile [path_to_the_.cairo_file] --output [desired_path_of_the_compiled_.json_file]`. For example:

```bash
cairo-compile cairo_programs/abs_value_array.cairo --output cairo_programs/abs_value_array_compiled.json
```

To run a compiled .json program through the VM, call the executable giving it the path and name of the file to be executed. For example:

```bash
target/release/cairo-rs-run cairo_programs/abs_value_array_compiled.json --layout all
```
The flag `--layout` determines which builtin is going to be used. More info about layouts [here](https://www.cairo-lang.org/docs/how_cairo_works/builtins.html#layouts).

To sum up, the following code will get you from zero to running a Cairo program:

Full compilation and execution example:
```bash
git clone https://github.com/lambdaclass/cairo-rs.git

Expand All @@ -58,11 +92,19 @@ cairo-compile cairo_programs/abs_value_array.cairo --output cairo_programs/abs_v

target/release/cairo-rs-run cairo_programs/abs_value_array_compiled.json --layout all
```
### Using hints

Currently, as this VM is under construction, it's missing some of the features of the original VM. Notably, this VM only implements a limited number of Python hints at the moment, while the [Python Cairo VM](https://github.com/starkware-libs/cairo-lang) allows users to run any Python code.

There are two ways to use non-standard hints in this VM:

- Extend the cairo-rs code and build your own binary using the interface hint processor
- Use [cairo-rs-py](https://github.com/lambdaclass/cairo-rs-py) which supports running any arbitrary hint in a Python interpreter.

### Running a function in a Cairo program with arguments
When running a Cairo program directly using the Cairo-rs repository you would first need to prepare a couple of things.

1. Specify the cairo program and the function you want to run
1. Specify the Cairo program and the function you want to run
```rust
let program =
Program::from_file(Path::new(&file_path), Some(&func_name));
Expand Down Expand Up @@ -91,7 +133,7 @@ cairo_runner.initialize_builtins(&mut vm)?;
cairo_runner.initialize_segments(&mut vm, None);
```

When using cairo-rs with the starknet devnet there are additional parameters that are part of the OS context passed on to the run_from_entrypoint function that we do not have here when using it directly. These parameters are, for example, initial stacks of the builtins, which are the base of each of them and are needed as they are the implicit arguments of the function.
When using cairo-rs with the Starknet devnet there are additional parameters that are part of the OS context passed on to the run_from_entrypoint function that we do not have here when using it directly. These parameters are, for example, initial stacks of the builtins, which are the base of each of them and are needed as they are the implicit arguments of the function.

```rust
let _var = cairo_runner.run_from_entrypoint(
Expand All @@ -113,16 +155,16 @@ A demo on how to use `cairo-rs` with WebAssembly can be found
[here](https://github.com/lambdaclass/cairo-rs-wasm).

### Testing
Run the test suite:
To run the test suite:
```bash
make test
```

## Code Coverage
## 🐊 Code Coverage

Track of the project's code coverage: [Codecov](https://app.codecov.io/gh/lambdaclass/cairo-rs).

## Benchmarks
## 🛕 Benchmarks

Running a [Cairo program](./cairo_programs/benchmarks/fibonacci_1000_multirun.cairo) that gets the 1000th Fibonacci number we got the following benchmarks:
* Execution time with [Criterion](./docs/benchmarks/criterion_benchmark.pdf)
Expand All @@ -134,16 +176,16 @@ Run the benchmark suite with cargo:
cargo bench
```

## Related Projects
## 🌞 Related Projects

- [starknet_in_rust](https://github.com/lambdaclass/starknet_in_rust): implementation of Starknet in Rust, powered by the cairo-rs VM.
- [cairo-rs-py](https://github.com/lambdaclass/cairo-rs-py): Bindings for using cairo-rs from Python code.

## Documentation
## 🌴 Documentation and further reading

### Cairo
* From Cairo Documentation: [How Cairo Works](https://www.cairo-lang.org/docs/how_cairo_works/index.html#how-cairo-works)
* [Cairo – a Turing-complete STARK-friendly CPU architecturer](https://eprint.iacr.org/2021/1063)
* [Cairo – a Turing-complete STARK-friendly CPU architecture](https://eprint.iacr.org/2021/1063)
* [A Verified Algebraic Representation of Cairo Program Execution](https://arxiv.org/pdf/2109.14534.pdf)
* [Cairo Verifier](https://github.com/patrickbiel01/Cairo_Verifier) in Rust

Expand Down Expand Up @@ -202,14 +244,14 @@ StarkWare's STARK Math blog series:
* [Low Degree Testing](https://medium.com/starkware/low-degree-testing-f7614f5172db)
* [A Framework for Efficient STARKs](https://medium.com/starkware/a-framework-for-efficient-starks-19608ba06fbe)

## Possible changes for the future
## 🏺 Possible changes for the future

* Make the alloc functionality an internal feature of the VM rather than a hint.

## Changelog
## ⚱️ Changelog

Keep track of the latest changes [here](CHANGELOG.md).
Keeps track of the latest changes [here](CHANGELOG.md).

## License
## 🐫 License

[MIT](/LICENSE)
9 changes: 9 additions & 0 deletions cairo_programs/common_signature.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
%builtins ecdsa
from starkware.cairo.common.serialize import serialize_word
from starkware.cairo.common.cairo_builtins import SignatureBuiltin
from starkware.cairo.common.signature import verify_ecdsa_signature

func main{ecdsa_ptr: SignatureBuiltin*}() {
verify_ecdsa_signature(2718, 1735102664668487605176656616876767369909409133946409161569774794110049207117, 3086480810278599376317923499561306189851900463386393948998357832163236918254, 598673427589502599949712887611119751108407514580626464031881322743364689811);
return();
}
26 changes: 26 additions & 0 deletions cairo_programs/test_skip_next_instruction.noretrocompat.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
func main{}() {
alloc_locals;
local x;
// This assertion will be skipped by vm.skip_next_instruction_execution
%{
skip_next_instruction()
%}
// This is an instruction of size 1
[ap] = 4;
[ap] = 5, ap++;

// This is an instruction of size 2
%{
skip_next_instruction()
%}
call should_fail;

x = 2;
assert x = 2;
return ();
}

func should_fail{}(a: felt) {
assert a = 1512482385392052380;
return ();
}
8 changes: 4 additions & 4 deletions docs/hint_processor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The purpose of this method is to organize the data related to hints in the way i
This method is called at the start of each VM step when there is a hint to execute.
It receives the dynamic structure created by `compile_hint` along with the program constants and a set of proxies containing a limited access to the VM's Internals:

* `exec_scopes_proxy` is the hint's gateaway to interact with the execution_scopes in the VM and share data bewteen hints without inserting them into the cairo execution. It provides methods to create and remove scopes and to modify the current scope, along with several helper methods to allow inserting and retrieving variables of specific types. This proxy only allows modifying the current scope, which is the last available scope before the hint's execution (Note that calling enter_scope and exit_scope wont change the current scope for the duration of the hint´s execution)
* `exec_scopes_proxy` is the hint's gateway to interact with the execution_scopes in the VM and share data between hints without inserting them into the cairo execution. It provides methods to create and remove scopes and to modify the current scope, along with several helper methods to allow inserting and retrieving variables of specific types. This proxy only allows modifying the current scope, which is the last available scope before the hint's execution (Note that calling enter_scope and exit_scope won't change the current scope for the duration of the hint´s execution)
* `vm_proxy` is the hint's gateway to the internal values of the VM, it provides mutable references to the memory segment manager and the run context, and immutable references to the builtin runners and the program's prime, it also contains a memory proxy:
* `MemoryProxy`: It grants a more limited access to the VM's memory, providing the necessary methods to modify it in a controlled manner.

Expand All @@ -44,12 +44,12 @@ The following helper functions are provided in hint_processor_utils.rs to simpli

These methods take the HintReference associated to the variable along with the hint's ApTracking data.

Note: When handling pointer type variables, computing the address and using it to get the variable from memory might not lead to the correct value (as the variable refrence may contain an immediate value that has to be added to the ptr itself), so using the functiom get_ptr_from_reference is strongly recomended.
Note: Cairo's memory is write-once, read-only, so when using `insert_value_from_reference` its important to first make sure that the variable doesnt contain any value (for example, it may be defined as local but never written) to avoid inconsistent memory errors
Note: When handling pointer type variables, computing the address and using it to get the variable from memory might not lead to the correct value (as the variable reference may contain an immediate value that has to be added to the ptr itself), so using the function get_ptr_from_reference is strongly recommended.
Note: Cairo's memory is write-once, read-only, so when using `insert_value_from_reference` it's important to first make sure that the variable doesn't contain any value (for example, it may be defined as local but never written) to avoid inconsistent memory errors

## BuiltinHintProcessor

The BuiltinHintProcessor is the default hint exector of the VM, it is able to execute hints from the common library + sha256
The BuiltinHintProcessor is the default hint executor of the VM, it is able to execute hints from the common library + sha256

## Usage Example

Expand Down
8 changes: 4 additions & 4 deletions docs/hint_processor/hint_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Requirements for hints
- Must cairo-rs support reuse of existing hints in starknet? Is it enough to enable re-writing these hints as python-embedded-in-cairo that uses a new API to interface with the cairo-rs VM state?
- Aside from mutable access to the memory manager and the registers, what do non-builtin hints require in terms of mutating the VM state? Is there anything that is explicitly not allowed or desireable, or that is currently allowed but would be better restricted?
- Aside from mutable access to the memory manager and the registers, what do non-builtin hints require in terms of mutating the VM state? Is there anything that is explicitly not allowed or desirable, or that is currently allowed but would be better restricted?
- What is the medium-long term plan for hints? Be able to implement hints as rust-embedded-in-cairo, support python hints ad aeternum, add support for more languages?
- We should go through the implementation of the syscall hints and think how they can be implemented with the current cairo-rs code, what is missing, etc.

Expand Down Expand Up @@ -40,8 +40,8 @@ Notes
- How to provide the embedded python interpreter access to cairo-rs VM state?
- How hard will converting between type representations be?
- One possibility that can be explored is writing a new implementation of MemorySegmentManager in python which works together with the python embedding mechanism, so that hints that get passed a reference to the MSM will be able to access cairo-rs instead of the python vm
- Another possibility that might be necesary is modifying the starknet hints in python to use a new interface mechanism.
- Of the three embedding options, cpython seems the most straighforward but also limited, pyo3 the most powerful, and rustpython the least mature
- Another possibility that might be necessary is modifying the starknet hints in python to use a new interface mechanism.
- Of the three embedding options, cpython seems the most straightforward but also limited, pyo3 the most powerful, and rustpython the least mature
- From [here](https://www.infoworld.com/article/3664124/how-to-use-rust-with-python-and-python-with-rust.html):
An important caveat with both cpython and PyO3 is to always minimize the number of times data is passed back and forth between the two languages.
Each call from Python to Rust or vice versa incurs some overhead.
Expand All @@ -55,7 +55,7 @@ Notes
- How to provide access to vm state, and allow state modification by hints?
- Should the hint code running in python intermittingly call an API to modify cairo-rs VM state, or should it run in completion, and send changes back to cairo-rs once done?
- Should this protocol send and receive a full vm state representation, or just some representation of the changes to state made by the hint?
- Open question: aside from the the api to indirectly modify cairo-rs vm state, what else is needed to allow hints to run? dependencies?
- Open question: aside from the api to indirectly modify cairo-rs vm state, what else is needed to allow hints to run? dependencies?
- How will having this python codebase affect testing, packaging, running, etc?
- (+) more easily extensible to other languages?
- (-) likely more overhead from state (de)serialization
Expand Down
Loading