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

[REPLACED] Set up memory output comparison for contracts run in starknet-devnet tests #163

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
368152e
Expose write_binary_memory method
Nov 29, 2022
28c9cff
Add patches and build script
Nov 29, 2022
d6f45ff
Draft steps on Makefile
Nov 29, 2022
2f9e060
Remove duplicate patch files
Nov 29, 2022
2a20de6
Add target to .PHONY
Nov 29, 2022
33d1b1e
Fix paths in build_envs script
Nov 29, 2022
876b8d2
Add starknet setup
Nov 29, 2022
5d6d678
Add more setup
Nov 29, 2022
f1373b6
Fix
Nov 29, 2022
0ced513
Start run_tests_compare_memory script
Nov 29, 2022
228f2d6
Add files to make clean
Nov 29, 2022
cf84748
Move env patching to makefile
Nov 29, 2022
64aa871
Add memory comparison to Makefile
Nov 29, 2022
7592c35
Finish script
Nov 29, 2022
c48c3ff
Complete makefile target
Nov 29, 2022
0528a42
Add compare-devnet-memory workflow
Nov 29, 2022
fc15bd1
Fix syntax
Nov 29, 2022
1cbb024
Fix workflow file
Nov 29, 2022
058f437
Clippy fix
Nov 29, 2022
ca86762
Remove ilegal option
Nov 29, 2022
cc2e8a0
Add python setup to workflow
Nov 29, 2022
4704322
Fix stuff
Nov 30, 2022
c33c942
Fix workflow
Nov 30, 2022
a15914c
Debugging
Nov 30, 2022
b8042bf
Debugging
Nov 30, 2022
e097100
Debugging
Nov 30, 2022
f083415
Debug
Nov 30, 2022
1108e7d
Debug
Nov 30, 2022
d708d55
Fix bash syntax
Nov 30, 2022
24485e0
Remove debug step
Nov 30, 2022
4d4233a
Add success message
Nov 30, 2022
1164c2f
Insert bug
Nov 30, 2022
9b941b5
Replace memory_comparator
Dec 1, 2022
3b13b36
Make new comparator executable
Dec 1, 2022
9b2ee59
Fix indentation
Dec 1, 2022
11c66ec
Filter out file which doesnt produce memory outputs in execute_entry_…
Dec 1, 2022
80e7f91
Filter out file which doesnt produce memory outputs
Dec 1, 2022
831c2da
Filter out file which doesnt produce memory outputs
Dec 1, 2022
e537487
Exclude more files
Dec 1, 2022
a7988f5
Remove bug
Dec 1, 2022
0662336
Merge branch 'main' into memory-comparison-devnet
Dec 1, 2022
deb8d09
Update patch file
Dec 1, 2022
4850a57
Fix patch
Dec 1, 2022
c257bcd
Include more tests
Dec 1, 2022
4b00ac4
Fix syntax
Dec 1, 2022
b17141f
Fix syntax
Dec 1, 2022
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
36 changes: 36 additions & 0 deletions .github/workflows/compare_memory_devnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: compare_devnet_memory

on:
push:
branches: [ main ]
pull_request:
branches: [ '*' ]

env:
CARGO_TERM_COLOR: always
jobs:
compare_memory_devnet:
runs-on: ubuntu-20.04
steps:
- name: Install Rust 1.61.0
uses: actions-rs/toolchain@v1
with:
toolchain: 1.61.0
override: true
components: rustfmt, clippy
- uses: actions/checkout@v3
- name: Python3 Build
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Checkout
uses: actions/checkout@v3
- name: Checkout starknet-devnet
uses: actions/checkout@v3
with:
repository: Shard-Labs/starknet-devnet
path: starknet-devnet
- name: Install test dependencies
run: pip install ecdsa fastecdsa sympy cairo-lang==0.9.1 maturin
- name: Run devnet tests & compare memory outputs
run: make compare_memory_devnet_ci
52 changes: 50 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: deps deps-macos deps-default-version build run check test clippy clean run-python-test full-test run-comparer-tracer compare_trace_memory compare_trace compare_memory
.PHONY: deps deps-macos deps-default-version build run check test clippy clean run-python-test full-test run-comparer-tracer compare_trace_memory compare_trace compare_memory compare_memory_devnet compare_memory_devnet_ci

TEST_DIR=cairo_programs
TEST_FILES:=$(wildcard $(TEST_DIR)/*.cairo)
Expand Down Expand Up @@ -78,6 +78,8 @@ clean:
rm -f $(BAD_TEST_DIR)/*.memory
rm -f $(BAD_TEST_DIR)/*.trace
rm -rf cairo-rs-py-env
rm -rf starknet-devnet
rm -rf scripts/memory_comparator/cairo*

run-python-test: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS)
PYENV_VERSION=pypy3.7-7.3.9 . cairo-rs-py-env/bin/activate && \
Expand All @@ -104,4 +106,50 @@ compare_trace: $(CAIRO_RS_TRACE) $(CAIRO_TRACE)
compare_memory: $(CAIRO_RS_MEM) $(CAIRO_MEM)
cd tests; ./compare_vm_state.sh memory


compare_memory_devnet:
# Set up the virtual envs
scripts/memory_comparator/build_envs.sh
# Clone the starknet-devnet from github
git clone [email protected]:Shard-Labs/starknet-devnet.git
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's checkout a fixed tag instead of main. We need stability for comparisons.

Comment on lines +110 to +113
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This belongs into a separate setup target.

# Set up the starknet-devnet in each env
# cairo-rs-py
. scripts/memory_comparator/cairo-rs-py/bin/activate && \
pip install starknet-devnet && \
cd starknet-devnet; scripts/install_dev_tools.sh
# cairo-lang
. scripts/memory_comparator/cairo-lang/bin/activate && \
pip install starknet-devnet && \
cd starknet-devnet; scripts/install_dev_tools.sh
# Create the folder where we will store the memory outputs
cd starknet-devnet; mkdir memory_files
# Compile test files
. scripts/memory_comparator/cairo-lang/bin/activate && \
cd starknet-devnet; scripts/compile_contracts.sh
# Patch both envs
patch --directory scripts/memory_comparator/cairo-rs-py/lib/python3.9/site-packages/ --strip 2 < scripts/memory_comparator/output-memory-cairo-rs-py.patch
patch --directory scripts/memory_comparator/cairo-lang/lib/python3.9/site-packages/ --strip 2 < scripts/memory_comparator/output-memory-cairo-lang.patch
Comment on lines +119 to +130
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the cairo-lang commands can run from a different target that builds the outputs, so it only runs once if we need to repeatedly run this test.

# Run each test one by one in each env and run the memory comparator
. ./scripts/memory_comparator/run_tests_compare_memory.sh

compare_memory_devnet_ci:
# Set up the virtual envs
scripts/memory_comparator/build_envs.sh
# Set up the starknet-devnet in each env
# cairo-rs-py
. scripts/memory_comparator/cairo-rs-py/bin/activate && \
pip install starknet-devnet && \
cd starknet-devnet; scripts/install_dev_tools.sh
# cairo-lang
. scripts/memory_comparator/cairo-lang/bin/activate && \
pip install starknet-devnet && \
cd starknet-devnet; scripts/install_dev_tools.sh
# Create the folder where we will store the memory outputs
cd starknet-devnet; mkdir memory_files
# Compile test files
. scripts/memory_comparator/cairo-lang/bin/activate && \
cd starknet-devnet; scripts/compile_contracts.sh
# Patch both envs
patch --directory scripts/memory_comparator/cairo-rs-py/lib/python3.9/site-packages/ --strip 2 < scripts/memory_comparator/output-memory-cairo-rs-py.patch
patch --directory scripts/memory_comparator/cairo-lang/lib/python3.9/site-packages/ --strip 2 < scripts/memory_comparator/output-memory-cairo-lang.patch
# Run each test one by one in each env and run the memory comparator
. ./scripts/memory_comparator/run_tests_compare_memory.sh
Comment on lines +134 to +155
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a lot of duplication.

16 changes: 16 additions & 0 deletions scripts/memory_comparator/build_envs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh

set -e

# This is not reaaaaally a robust way to find it, but you need to be actively
# trying to break it for this to fail :)
SCRIPT_DIR="scripts/memory_comparator"

python3.9 -m venv --upgrade-deps ${SCRIPT_DIR}/cairo-lang ${SCRIPT_DIR}/cairo-rs-py
${SCRIPT_DIR}/cairo-lang/bin/pip install cairo-lang==0.10.1
${SCRIPT_DIR}/cairo-rs-py/bin/pip install maturin==0.14.1 cairo-lang==0.10.1
${SCRIPT_DIR}/cairo-rs-py/bin/maturin build --manifest-path Cargo.toml --release --strip --interpreter 3.9 --no-default-features --features extension
${SCRIPT_DIR}/cairo-rs-py/bin/pip install target/wheels/cairo_rs_py-*.whl

${SCRIPT_DIR}/cairo-rs-py/bin/cairo-run --version
${SCRIPT_DIR}/cairo-rs-py/bin/starknet --version
Comment on lines +1 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we copy-pasting this script?

57 changes: 57 additions & 0 deletions scripts/memory_comparator/memory_comparator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env python3

import sys

def main():
filename1 = sys.argv[1]
filename2 = sys.argv[2]
cairo_mem = {}
cairo_rs_mem = {}
name = filename2.split("/")[-1]
with open(filename1, 'rb') as f:
cairo_raw = f.read()
assert len(cairo_raw) % 40 == 0, f'{filename1}: malformed memory file from Cairo VM'
chunks = len(cairo_raw) // 40
for i in range(0, chunks):
chunk = cairo_raw[i*40:(i+1)*40]
k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little')
assert k not in cairo_mem, f'{filename1}: address {k} has two values'
cairo_mem[k] = v
assert len(cairo_mem) * 40 == len(cairo_raw), f'{filename1}: {len(cairo_mem) * 40} != {len(cairo_raw)}'

with open(filename2, 'rb') as f:
cairo_rs_raw = f.read()
assert len(cairo_rs_raw) % 40 == 0, f'{filename2}: malformed memory file from cairo-rs'
chunks = len(cairo_rs_raw) // 40
for i in range(0, chunks):
chunk = cairo_rs_raw[i*40:(i+1)*40]
k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little')
assert k not in cairo_rs_mem, f'{filename2}: address {k} has two values'
cairo_rs_mem[k] = v
assert len(cairo_rs_mem) * 40 == len(cairo_rs_raw), f'{filename2}: {len(cairo_rs_mem) * 40} != {len(cairo_rs_raw)}'

assert len(cairo_mem) == len(cairo_rs_mem), f'{filename2}: len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}'
if cairo_mem != cairo_rs_mem:
print(f'Mismatch between {filename1} (Cairo) and {filename2} (cairo_rs)')
print('keys in Cairo but not cairo-rs:')
for k in cairo_mem:
if k in cairo_rs_mem:
continue
print(f'{k}:{v}')
print('keys in cairo_rs but not Cairo:')
for k in cairo_rs_mem:
if k in cairo_mem:
continue
print(f'{k}:{v}')
print('mismatched values (Cairo <-> cairo_rs)):')
for k in cairo_rs_mem:
if k not in cairo_mem:
continue
if cairo_rs_mem[k] == cairo_mem[k]:
continue
print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})')
exit(1)


if __name__ == '__main__':
main()
51 changes: 51 additions & 0 deletions scripts/memory_comparator/output-memory-cairo-lang.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
diff --git a/src/starkware/starknet/business_logic/execution/execute_entry_point.py b/src/starkware/starknet/business_logic/execution/execute_entry_point.py
index 62d4290..f4a0d8b 100644
--- a/src/starkware/starknet/business_logic/execution/execute_entry_point.py
+++ b/src/starkware/starknet/business_logic/execution/execute_entry_point.py
@@ -9,6 +9,8 @@ from starkware.cairo.lang.vm.relocatable import RelocatableValue
from starkware.cairo.lang.vm.security import SecurityError
from starkware.cairo.lang.vm.utils import ResourcesError
from starkware.cairo.lang.vm.vm_exceptions import HintException, VmException, VmExceptionBase
+from starkware.cairo.lang.vm.cairo_run import write_binary_memory
+import math
from starkware.starknet.business_logic.execution.execute_entry_point_base import (
ExecuteEntryPointBase,
)
@@ -274,6 +276,10 @@ class ExecuteEntryPoint(ExecuteEntryPointBase):
assert isinstance(args_ptr, RelocatableValue) # Downcast.
runner.mark_as_accessed(address=args_ptr, size=len(entry_points_args))

+ f = open("memory_files/execute_entry_point.memory", "wb")
+ field_bytes = math.ceil(contract_class.program.prime.bit_length() / 8)
+ runner.relocate()
+ write_binary_memory(f, runner.relocated_memory, field_bytes)
return runner, syscall_handler

def _get_selected_entry_point(
diff --git a/src/starkware/starknet/core/os/class_hash.py b/src/starkware/starknet/core/os/class_hash.py
index 132fb21..321c63a 100644
--- a/src/starkware/starknet/core/os/class_hash.py
+++ b/src/starkware/starknet/core/os/class_hash.py
@@ -3,9 +3,11 @@ import dataclasses
import itertools
import json
import os
+import math
from contextvars import ContextVar
from functools import lru_cache
from typing import Callable, List, Optional
+from starkware.cairo.lang.vm.cairo_run import write_binary_memory

import cachetools

@@ -92,6 +94,10 @@ def compute_class_hash_inner(
use_full_name=True,
verify_secure=False,
)
+ f = open("memory_files/class_hash.memory", "wb")
+ field_bytes = math.ceil(program.prime.bit_length() / 8)
+ runner.relocate()
+ write_binary_memory(f, runner.relocated_memory, field_bytes)
_, class_hash = runner.get_return_values(2)
return class_hash

Loading