Skip to content

Commit

Permalink
Cairo v0.9.1.
Browse files Browse the repository at this point in the history
  • Loading branch information
liorgold2 committed Jul 19, 2022
1 parent 167b28b commit 13cef10
Show file tree
Hide file tree
Showing 86 changed files with 1,986 additions and 422 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Once the docker image is built, you can fetch the python package zip file using:

```bash
> container_id=$(docker create cairo)
> docker cp ${container_id}:/app/cairo-lang-0.9.0.zip .
> docker cp ${container_id}:/app/cairo-lang-0.9.1.zip .
> docker rm -v ${container_id}
```

26 changes: 20 additions & 6 deletions src/cmake_utils/gen_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ def get_pth_dir(python: str, venv_dir: str):
raise NotImplementedError(f"Unsupported python executable {python}")


def find_python(exec_name: str) -> str:
"""
Tries to find Python executable in well known paths.
Arguments:
exec_name: Expected name of the Python executable, for example `python3.7`.
"""

path = "/usr/bin:/usr/local/bin:" + os.getenv("PATH", default="")
python_exec = shutil.which(exec_name, path=path)
if python_exec is not None:
return python_exec

raise RuntimeError(
f"Unable to find Python executable named {exec_name} in PATH or well known directories."
)


def main():
parser = ArgumentParser(description="Generates a virtual environment.")
parser.add_argument(
Expand All @@ -101,12 +119,8 @@ def main():
shutil.rmtree(args.site_dir, ignore_errors=True)
os.makedirs(args.site_dir)

# Find python.
lookup_paths = [
"/usr/bin",
"/usr/local/bin",
]
python_exec = shutil.which(args.python, path=":".join(lookup_paths))
python_exec = find_python(args.python)

# Prepare an empty virtual environment in the background.
# --symlinks prefers symlinks of copying.
# --without-pip installs a completely empty venv, with no pip.
Expand Down
5 changes: 4 additions & 1 deletion src/demo/amm_demo/amm.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ func modify_account{range_check_ptr}(state : AmmState, account_id, diff_a, diff_
assert new_account.token_b_balance = new_token_b_balance

# Perform the account update.
# Note that dict_write() will update the 'account_dict_end'
# reference.
let (__fp__, _) = get_fp_and_pc()
dict_write{dict_ptr=account_dict_end}(key=account_id, new_value=cast(&new_account, felt))

# Construct and return the new state.
# Construct and return the new state with the updated
# 'account_dict_end'.
local new_state : AmmState
assert new_state.account_dict_start = (
state.account_dict_start)
Expand Down
10 changes: 8 additions & 2 deletions src/services/everest/api/feeder_gateway/response_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass


class BaseResponseObject(ValidatedMarshmallowDataclass):
class BaseResponseObject:
"""
Contains common functionality to response objects from the FeederGateway.
This class must not contain a marshmallow schema and should not be directly (de)serialized.
"""

@marshmallow.post_dump
def remove_none_values(self, data: Dict[Any, Any], many: bool = False) -> Dict[Any, Any]:
return {key: value for key, value in data.items() if value is not None}


class ValidatedResponseObject(BaseResponseObject, ValidatedMarshmallowDataclass):
"""
Validated version of BaseResponseObject.
This class must not contain a marshmallow schema and should not be directly (de)serialized.
"""
4 changes: 4 additions & 0 deletions src/starkware/cairo/common/cairo_blake2s/blake2s.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# This module provides a set of functions to compute the blake2s hash function.
#
# This module is similar to the keccak.cairo module. See more info there.

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_blake2s.packed_blake2s import N_PACKED_INSTANCES, blake2s_compress
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
Expand Down
41 changes: 40 additions & 1 deletion src/starkware/cairo/common/cairo_keccak/keccak.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# This module provides a set of functions to compute the (Ethereuem compatible) keccak hash
# function.
#
# In order to use the functions that get the ``keccak_ptr`` implicit argument
# (e.g., ``keccak_uint256s()``, ``keccak()``, ...) you should:
#
# 1. Create a new memory segment using ``alloc()`` and store it in a variable named
# ``keccak_ptr``.
# 2. Create a copy of the pointer, and name it ``keccak_ptr_start``, before using keccak.
# 3. Use the keccak functions with the ``keccak_ptr`` implicit argument
# (either use the ``with`` statement or write ``{keccak_ptr=keccak_ptr}`` explicitly).
# 4. Call ``finalize_keccak()`` (once) at the end of your program/transaction.
#
# For example:
#
# let (keccak_ptr : felt*) = alloc()
# local keccak_ptr_start : felt* = keccak_ptr
#
# with keccak_ptr:
# keccak_uint256s(...)
# keccak_uint256s(...)
# end
#
# finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr)
#
# It's more efficient to reuse the ``keccak_ptr`` segment for all the keccak functions you need,
# and call ``finalize_keccak()`` once, because of an internal batching done inside
# ``finalize_keccak()``.
#
# Failing to call ``finalize_keccak()``, will make the keccak function unsound - the prover will be
# able to choose any value as the keccak's result.
#
# The module also provides a set of helper functions to prepare the input data for keccak,
# such as ``keccak_add_uint256()`` and ``keccak_add_felt()``. To use them, you should allocate
# a new memory segment to variable named ``inputs`` (this value is an implicit argument to those
# functions). Once the input is ready, you should call ``keccak()`` or ``keccak_bigend()``.
# Don't forget to call ``finalize_keccak()`` at the end of the program/transaction.

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.bitwise import bitwise_and, bitwise_or, bitwise_xor
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
Expand Down Expand Up @@ -368,7 +406,8 @@ func _keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}
return (keccak_ptr - KECCAK_STATE_SIZE_FELTS)
end

# Verifies that the results of keccak() are valid.
# Verifies that the results of keccak() are valid. For optimization, this can be called only once
# after all the keccak calculations are completed.
func finalize_keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(
keccak_ptr_start : felt*, keccak_ptr_end : felt*
):
Expand Down
4 changes: 2 additions & 2 deletions src/starkware/cairo/common/cairo_secp/signature.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ end
# Verifies a Secp256k1 ECDSA signature.
# Also verifies that r and s are in the range (0, N), that their limbs are in the range
# [0, BASE), and that v is in the range [0, 2 ** 128).
# Receives a keccak_ptr for computing keccak. finalize_keccak should be called after all the keccak
# calculations are done.
# Receives a keccak_ptr for computing keccak. finalize_keccak should be called by the function's
# caller after all the keccak calculations are done.
# Assumptions:
# * All the limbs of msg_hash are in the range [0, 3 * BASE).
func verify_eth_signature{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}(
Expand Down
2 changes: 1 addition & 1 deletion src/starkware/cairo/lang/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.0
0.9.1
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ def add_signature(self, addr, signature):
assert isinstance(
addr, RelocatableValue
), f"Expected memory address to be relocatable value. Found: {addr}."
assert (
addr.segment_index == self.base.segment_index
), f"Signature hint must point to the signature builtin segment, not {addr}."
assert (
addr.offset % CELLS_PER_SIGNATURE == 0
), f"Signature hint must point to the public key cell, not {addr}."
Expand Down
14 changes: 11 additions & 3 deletions src/starkware/cairo/lang/compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,20 @@ python_lib(cairo_compile_lib
offset_reference.py
parser_transformer.py
parser.py
preprocessor/__init__.py
preprocessor/auxiliary_info_collector.py
preprocessor/bool_expr/__init__.py
preprocessor/bool_expr/errors.py
preprocessor/bool_expr/lowering.py
preprocessor/bool_expr/lowering_test_utils.py
preprocessor/compound_expressions.py
preprocessor/default_pass_manager.py
preprocessor/dependency_graph.py
preprocessor/directives.py
preprocessor/flow.py
preprocessor/identifier_aware_visitor.py
preprocessor/identifier_collector.py
preprocessor/if_labels.py
preprocessor/local_variables.py
preprocessor/memento.py
preprocessor/pass_manager.py
Expand All @@ -63,7 +69,6 @@ python_lib(cairo_compile_lib
preprocessor/preprocessor.py
preprocessor/reg_tracking.py
preprocessor/struct_collector.py
preprocessor/unique_labels.py
program.py
proxy_identifier_manager.py
references.py
Expand All @@ -74,6 +79,7 @@ python_lib(cairo_compile_lib
type_system_visitor.py
type_system.py
type_utils.py
unique_name_provider.py

LIBS
cairo_constants_lib
Expand Down Expand Up @@ -147,25 +153,27 @@ full_python_test(cairo_compile_test
parser_errors_test.py
parser_test_utils.py
parser_test.py
preprocessor/memento_test.py
preprocessor/bool_expr/lowering_test.py
preprocessor/compound_expressions_test.py
preprocessor/conftest.py
preprocessor/dependency_graph_test.py
preprocessor/flow_test.py
preprocessor/identifier_aware_visitor_test.py
preprocessor/identifier_collector_test.py
preprocessor/if_labels_test.py
preprocessor/local_variables_test.py
preprocessor/memento_test.py
preprocessor/preprocessor_test.py
preprocessor/reg_tracking_test.py
preprocessor/struct_collector_test.py
preprocessor/unique_labels_test.py
proxy_identifier_manager_test.py
references_test.py
resolve_search_result_test.py
scoped_name_test.py
type_casts_test.py
type_system_visitor_test.py
type_utils_test.py
unique_name_provider_test.py

LIBS
cairo_compile_lib
Expand Down
4 changes: 2 additions & 2 deletions src/starkware/cairo/lang/compiler/assembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager
from starkware.cairo.lang.compiler.instruction_builder import build_instruction
from starkware.cairo.lang.compiler.preprocessor.preprocessor import PreprocessedProgram
from starkware.cairo.lang.compiler.preprocessor.unique_labels import is_anonymous_label
from starkware.cairo.lang.compiler.program import CairoHint, Program
from starkware.cairo.lang.compiler.scoped_name import ScopedName
from starkware.cairo.lang.compiler.unique_name_provider import UniqueNameProvider


def assemble(
Expand Down Expand Up @@ -66,7 +66,7 @@ def assemble(
{
name: identifier_definition
for name, identifier_definition in preprocessed_program.identifiers.as_dict().items()
if not is_anonymous_label(name.path[-1])
if not UniqueNameProvider.is_name_unique(name.path[-1])
}
)

Expand Down
5 changes: 5 additions & 0 deletions src/starkware/cairo/lang/compiler/ast/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ def get_particles(self):

def get_children(self) -> Sequence[Optional[AstNode]]:
return self.identifiers

@classmethod
def from_identifiers(cls, identifiers: List[TypedIdentifier], **kwargs) -> "IdentifierList":
notes = [Notes() for _ in range(len(identifiers) + 1)]
return IdentifierList(identifiers=identifiers, notes=notes, **kwargs)
59 changes: 55 additions & 4 deletions src/starkware/cairo/lang/compiler/ast/bool_expr.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,73 @@
import dataclasses
from abc import ABC, abstractmethod
from typing import Optional, Sequence

from starkware.cairo.lang.compiler.ast.expr import Expression
from starkware.cairo.lang.compiler.ast.formatting_utils import LocationField
from starkware.cairo.lang.compiler.ast.formatting_utils import (
LocationField,
Particle,
ParticleList,
SingleParticle,
)
from starkware.cairo.lang.compiler.ast.node import AstNode
from starkware.cairo.lang.compiler.ast.notes import Notes, NotesField
from starkware.cairo.lang.compiler.error_handling import Location


class BoolExpr(AstNode, ABC):
"""
Base class for all boolean expressions.
"""

location: Optional[Location] = LocationField

@abstractmethod
def to_particle(self) -> Particle:
"""
Get formatting particle for this expression.
"""


@dataclasses.dataclass
class BoolExpr(AstNode):
class BoolEqExpr(BoolExpr):
"""
Represents a trivial (in)equality comparison between two expressions.
This is the most primitive building block of conditions in ``if`` code element.
"""

a: Expression
b: Expression
eq: bool
notes: Notes = NotesField
location: Optional[Location] = LocationField

def get_particles(self):
def to_particle(self) -> Particle:
self.notes.assert_no_comments()
relation = "==" if self.eq else "!="
return [f"{self.a.format()} {relation} ", self.b.format()]
return SingleParticle(f"{self.a.format()} {relation} {self.b.format()}")

def get_children(self) -> Sequence[Optional[AstNode]]:
return [self.a, self.b]


@dataclasses.dataclass
class BoolAndExpr(BoolExpr):
"""
Represents logical conjunction of two ``BoolExpr``s (``and`` operator).
"""

a: BoolExpr
b: BoolEqExpr
notes: Notes = NotesField
location: Optional[Location] = LocationField

def to_particle(self) -> Particle:
self.notes.assert_no_comments()
a = self.a.to_particle()
a.add_suffix(" and ")
b = self.b.to_particle()
return ParticleList([a, b])

def get_children(self) -> Sequence[Optional[AstNode]]:
return [self.a, self.b]
33 changes: 29 additions & 4 deletions src/starkware/cairo/lang/compiler/ast/code_elements.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dataclasses
from abc import abstractmethod
from typing import Any, Dict, List, Optional, Sequence, Union
from typing import Any, Dict, Iterable, List, Optional, Sequence, Union

from starkware.cairo.lang.compiler.ast.aliased_identifier import AliasedIdentifier
from starkware.cairo.lang.compiler.ast.arguments import IdentifierList
Expand Down Expand Up @@ -418,6 +418,30 @@ def format(self, allowed_line_length):
def get_children(self) -> Sequence[Optional[AstNode]]:
return self.code_elements

def __add__(self, other: "CodeBlock") -> "CodeBlock":
assert isinstance(other, self.__class__)
return CodeBlock(code_elements=self.code_elements + other.code_elements)

@classmethod
def from_code_elements(cls, code_elements: Iterable[CodeElement]) -> "CodeBlock":
return cls(
code_elements=[
CommentedCodeElement(
code_elm=elm,
comment=None,
location=getattr(elm, "location", None),
)
for elm in code_elements
]
)

@classmethod
def singleton(cls, code_element: CodeElement) -> "CodeBlock":
"""
Shortcut for ``from_code_elements([code_element])``.
"""
return cls.from_code_elements([code_element])


@dataclasses.dataclass
class CodeElementScoped(CodeElement):
Expand Down Expand Up @@ -601,10 +625,11 @@ class CodeElementIf(CodeElement):
location: Optional[Location] = LocationField

def format(self, allowed_line_length):
cond_particles = ["if ", *self.condition.get_particles()]
cond_particles[-1] = cond_particles[-1] + ":"
cond_particle = self.condition.to_particle()
cond_particle.add_prefix("if ")
cond_particle.add_suffix(":")
code = particles_in_lines(
particles=ParticleList(elements=cond_particles),
particles=cond_particle,
config=ParticleFormattingConfig(
allowed_line_length=allowed_line_length, line_indent=INDENTATION
),
Expand Down
Loading

0 comments on commit 13cef10

Please sign in to comment.