Skip to content

Commit

Permalink
Cairo v0.4.2.
Browse files Browse the repository at this point in the history
  • Loading branch information
liorgold2 committed Oct 2, 2021
1 parent c25f826 commit f464ec4
Show file tree
Hide file tree
Showing 21 changed files with 420 additions and 108 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ We recommend starting from [Setting up the environment](https://cairo-lang.org/d
# Installation instructions

You should be able to download the python package zip file directly from
[github](https://github.com/starkware-libs/cairo-lang/releases/tag/v0.4.1)
[github](https://github.com/starkware-libs/cairo-lang/releases/tag/v0.4.2)
and install it using ``pip``.
See [Setting up the environment](https://cairo-lang.org/docs/quickstart.html).

Expand Down 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.4.1.zip .
> docker cp ${container_id}:/app/cairo-lang-0.4.2.zip .
> docker rm -v ${container_id}
```

1 change: 1 addition & 0 deletions src/services/everest/business_logic/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def _apply(self):
@contextlib.contextmanager
def copy_and_apply(self) -> Iterator[TCarriedState]:
copied_state = self._copy()
# The exit logic will not be called in case an exception is raised inside the context.
yield copied_state
copied_state._apply() # Apply to self.

Expand Down
1 change: 1 addition & 0 deletions src/starkware/cairo/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ python_lib(cairo_common_lib
alloc.cairo
bitwise.cairo
cairo_builtins.cairo
cairo_blake2s/blake2s_utils.py
cairo_keccak/keccak_utils.py
cairo_sha256/sha256_utils.py
default_dict.cairo
Expand Down
86 changes: 86 additions & 0 deletions src/starkware/cairo/common/cairo_blake2s/blake2s_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from typing import List, Tuple

IV = [
0x6A09E667,
0xBB67AE85,
0x3C6EF372,
0xA54FF53A,
0x510E527F,
0x9B05688C,
0x1F83D9AB,
0x5BE0CD19,
]

SIGMA = [
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
[11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
[7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
[9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
[2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
[12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
[13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
[6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
[10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
]


def right_rot(value, n):
return (value >> n) | ((value & (2 ** n - 1)) << (32 - n))


def blake2s_compress(
h: List[int], message: List[int], t0: int, t1: int, f0: int, f1: int
) -> List[int]:
"""
h is a list of 8 32-bit words.
message is a list of 16 32-bit words.
"""
state = h + IV[:4] + [x % 2 ** 32 for x in [IV[4] ^ t0, IV[5] ^ t1, IV[6] ^ f0, IV[7] ^ f1]]
for i in range(10):
state = blake_round(state, message, SIGMA[i])
return [x ^ v0 ^ v1 for x, v0, v1 in zip(h, state[:8], state[8:])]


def blake_round(state: List[int], message: List[int], sigma: List[int]) -> List[int]:
state = list(state)
state[0], state[4], state[8], state[12] = mix(
state[0], state[4], state[8], state[12], message[sigma[0]], message[sigma[1]]
)
state[1], state[5], state[9], state[13] = mix(
state[1], state[5], state[9], state[13], message[sigma[2]], message[sigma[3]]
)
state[2], state[6], state[10], state[14] = mix(
state[2], state[6], state[10], state[14], message[sigma[4]], message[sigma[5]]
)
state[3], state[7], state[11], state[15] = mix(
state[3], state[7], state[11], state[15], message[sigma[6]], message[sigma[7]]
)

state[0], state[5], state[10], state[15] = mix(
state[0], state[5], state[10], state[15], message[sigma[8]], message[sigma[9]]
)
state[1], state[6], state[11], state[12] = mix(
state[1], state[6], state[11], state[12], message[sigma[10]], message[sigma[11]]
)
state[2], state[7], state[8], state[13] = mix(
state[2], state[7], state[8], state[13], message[sigma[12]], message[sigma[13]]
)
state[3], state[4], state[9], state[14] = mix(
state[3], state[4], state[9], state[14], message[sigma[14]], message[sigma[15]]
)

return state


def mix(a: int, b: int, c: int, d: int, m0: int, m1: int) -> Tuple[int, int, int, int]:
a = (a + b + m0) % 2 ** 32
d = right_rot((d ^ a), 16)
c = (c + d) % 2 ** 32
b = right_rot((b ^ c), 12)
a = (a + b + m1) % 2 ** 32
d = right_rot((d ^ a), 8)
c = (c + d) % 2 ** 32
b = right_rot((b ^ c), 7)

return a, b, c, d
2 changes: 1 addition & 1 deletion src/starkware/cairo/lang/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.1
0.4.2
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
ExprConst,
ExprDeref,
Expression,
ExprHint,
ExprFutureLabel,
ExprHint,
ExprIdentifier,
ExprNeg,
ExprOperator,
Expand Down
2 changes: 1 addition & 1 deletion src/starkware/cairo/lang/ide/vscode-cairo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "cairo",
"displayName": "Cairo",
"description": "Support Cairo syntax",
"version": "0.4.1",
"version": "0.4.2",
"engines": {
"vscode": "^1.30.0"
},
Expand Down
4 changes: 2 additions & 2 deletions src/starkware/cairo/lang/vm/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ def load_hints(self, program: Program, program_base: MaybeRelocatable):
compiled=self.compile_hint(
hint.code, f"<hint{hint_id}>", hint_index=hint_index
),
# Use hint=hint in the lambda's arguments to capture this value (otherwise, it
# will use the same hint object for all iterations).
# Use hint=hint in the lambda's arguments to capture this value (otherwise,
# it will use the same hint object for all iterations).
consts=lambda pc, ap, fp, memory, hint=hint: VmConsts(
context=VmConstsContext(
identifiers=program.identifiers,
Expand Down
1 change: 1 addition & 0 deletions src/starkware/starknet/business_logic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ python_lib(starknet_internal_transaction_lib
starkware_utils_lib
pip_marshmallow
pip_marshmallow_dataclass
pip_marshmallow_enum
pip_marshmallow_oneofschema
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import dataclasses
import logging
from abc import abstractmethod
from dataclasses import field
from typing import Dict, Iterable, List, Optional, Set, Tuple, cast
Expand All @@ -16,12 +17,16 @@
from starkware.cairo.lang.vm.utils import RunResources
from starkware.starknet.business_logic.state import CarriedState, StateSelector
from starkware.starknet.definitions import fields
from starkware.starknet.definitions.error_codes import StarknetErrorCode
from starkware.starknet.definitions.general_config import StarknetGeneralConfig
from starkware.starknet.services.api.gateway.transaction import Transaction
from starkware.starkware_utils.config_base import Config
from starkware.starkware_utils.error_handling import StarkException
from starkware.starkware_utils.marshmallow_dataclass_fields import SetField
from starkware.starkware_utils.validated_dataclass import ValidatedDataclass

logger = logging.getLogger(__name__)


@dataclasses.dataclass(frozen=True)
class L2ToL1MessageInfo(ValidatedDataclass):
Expand Down Expand Up @@ -190,9 +195,20 @@ async def apply_state_updates(
assert isinstance(general_config, StarknetGeneralConfig)

with state.copy_and_apply() as state_to_update:
execution_info = await self._apply_specific_state_updates(
state=state_to_update, general_config=general_config
)
try:
execution_info = await self._apply_specific_state_updates(
state=state_to_update, general_config=general_config
)
except StarkException:
# Raise StarkException-s as-is, so failure information is not lost.
raise
except Exception as exception:
# Wrap all exceptions with StarkException, so the Batcher can continue running
# even after unexpected errors.
logger.error(f"Unexpected failure; exception details: {exception}.", exc_info=True)
raise StarkException(
code=StarknetErrorCode.UNEXPECTED_FAILURE, message=str(exception)
)

return execution_info

Expand Down
1 change: 1 addition & 0 deletions src/starkware/starknet/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ python_lib(starknet_cli_lib

LIBS
cairo_compile_lib
cairo_tracer_lib
cairo_version_lib
cairo_vm_utils_lib
services_external_api_lib
Expand Down
9 changes: 7 additions & 2 deletions src/starkware/starknet/cli/starknet_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from starkware.cairo.lang.compiler.program import Program
from starkware.cairo.lang.compiler.type_system import mark_type_resolved
from starkware.cairo.lang.compiler.type_utils import check_felts_only_type
from starkware.cairo.lang.tracer.tracer_data import field_element_repr
from starkware.cairo.lang.version import __version__
from starkware.cairo.lang.vm.reconstruct_traceback import reconstruct_traceback
from starkware.starknet.compiler.compile import get_selector_from_name
Expand All @@ -26,6 +27,10 @@
from starkware.starkware_utils.error_handling import StarkErrorCode


def felt_formatter(hex_felt: str) -> str:
return field_element_repr(val=int(hex_felt, 16), prime=fields.FeltField.upper_bound)


def get_gateway_client(args) -> GatewayClient:
gateway_url = os.environ.get("STARKNET_GATEWAY_URL")
if args.gateway_url is not None:
Expand Down Expand Up @@ -184,7 +189,7 @@ async def invoke_or_call(args, command_args, call: bool):
if call:
feeder_client = get_feeder_gateway_client(args)
gateway_response = await feeder_client.call_contract(tx, args.block_id)
print(*gateway_response["result"])
print(*map(felt_formatter, gateway_response["result"]))
else:
gateway_client = get_gateway_client(args)
gateway_response = await gateway_client.add_transaction(tx=tx)
Expand Down Expand Up @@ -262,7 +267,7 @@ def handle_network_param(args):
network = os.environ.get("STARKNET_NETWORK") if args.network is None else args.network
if network is not None:
if network != "alpha":
print(f"Unknown network '{network}'.")
print(f"Unknown network '{network}'.", file=sys.stderr)
return 1

dns = "alpha2.starknet.io"
Expand Down
40 changes: 33 additions & 7 deletions src/starkware/starknet/compiler/data_encoder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dataclasses
from enum import Enum, auto
from typing import List, Optional, Sequence, Tuple
from typing import Callable, List, Optional, Sequence, Tuple

from starkware.cairo.lang.compiler.ast.cairo_types import (
CairoType,
Expand Down Expand Up @@ -313,25 +313,49 @@ def decode_data(


class DataEncoder(DataEncodingProcessor):
def __init__(
self,
arg_name_func: Callable[[ArgumentInfo], str],
encoding_type: EncodingType,
has_range_check_builtin: bool,
identifiers: IdentifierManager,
):
"""
Constructs a DataEncoder instance.
arg_name_func is a function that get ArgumentInfo and returns the name of the reference
containing that argument.
"""
super().__init__(
encoding_type=encoding_type,
has_range_check_builtin=has_range_check_builtin,
identifiers=identifiers,
)
self.arg_name_func = arg_name_func

def process_felt(self, arg_info: ArgumentInfo):
return f"""\
assert [__{self.var_name}_ptr] = {arg_info.name}
assert [__{self.var_name}_ptr] = {self.arg_name_func(arg_info)}
let __{self.var_name}_ptr = __{self.var_name}_ptr + 1
"""

def process_felt_ptr(self, arg_info: ArgumentInfo):
return f"""\
# Check that the length is non-negative.
assert [range_check_ptr] = {arg_info.name}_len
assert [range_check_ptr] = {self.arg_name_func(arg_info)}_len
# Store the updated range_check_ptr as a local variable to keep it available after
# the memcpy.
local range_check_ptr = range_check_ptr + 1
# Keep a reference to __{self.var_name}_ptr.
let __{self.var_name}_ptr_copy = __{self.var_name}_ptr
# Store the updated __{self.var_name}_ptr as a local variable to keep it available after
# the memcpy.
local __{self.var_name}_ptr : felt* = __{self.var_name}_ptr + {arg_info.name}_len
memcpy(dst=__{self.var_name}_ptr_copy, src={arg_info.name}, len={arg_info.name}_len)
local __{self.var_name}_ptr : felt* = __{self.var_name}_ptr + \
{self.arg_name_func(arg_info)}_len
memcpy(
dst=__{self.var_name}_ptr_copy,
src={self.arg_name_func(arg_info)},
len={self.arg_name_func(arg_info)}_len)
"""

def process_felts_object(self, arg_info: ArgumentInfo, size: int):
Expand All @@ -340,8 +364,8 @@ def process_felts_object(self, arg_info: ArgumentInfo, size: int):
for i in range(size)
)
return f"""\
# Create a reference to {arg_info.name} as felt*.
let __{self.var_name}_tmp : felt* = cast(&{arg_info.name}, felt*)
# Create a reference to {self.arg_name_func(arg_info)} as felt*.
let __{self.var_name}_tmp : felt* = cast(&{self.arg_name_func(arg_info)}, felt*)
{body}
let __{self.var_name}_ptr = __{self.var_name}_ptr + {size}
"""
Expand All @@ -352,9 +376,11 @@ def encode_data(
encoding_type: EncodingType,
has_range_check_builtin: bool,
identifiers: IdentifierManager,
arg_name_func: Callable[[ArgumentInfo], str] = lambda arg_info: arg_info.name,
) -> List[CommentedCodeElement]:

parser = DataEncoder(
arg_name_func=arg_name_func,
encoding_type=encoding_type,
has_range_check_builtin=has_range_check_builtin,
identifiers=identifiers,
Expand Down
15 changes: 8 additions & 7 deletions src/starkware/starknet/compiler/data_encoder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,31 +182,32 @@ def test_encode_data_for_return():
encoding_type=EncodingType.RETURN,
has_range_check_builtin=True,
identifiers=identifiers,
arg_name_func=lambda arg_info: f"x.{arg_info.name}",
)

assert (
"".join(code_element.format(100) + "\n" for code_element in code_elements)
== """\
assert [__return_value_ptr] = a
assert [__return_value_ptr] = x.a
let __return_value_ptr = __return_value_ptr + 1
assert [__return_value_ptr] = b_len
assert [__return_value_ptr] = x.b_len
let __return_value_ptr = __return_value_ptr + 1
# Check that the length is non-negative.
assert [range_check_ptr] = b_len
assert [range_check_ptr] = x.b_len
# Store the updated range_check_ptr as a local variable to keep it available after
# the memcpy.
local range_check_ptr = range_check_ptr + 1
# Keep a reference to __return_value_ptr.
let __return_value_ptr_copy = __return_value_ptr
# Store the updated __return_value_ptr as a local variable to keep it available after
# the memcpy.
local __return_value_ptr : felt* = __return_value_ptr + b_len
memcpy(dst=__return_value_ptr_copy, src=b, len=b_len)
local __return_value_ptr : felt* = __return_value_ptr + x.b_len
memcpy(dst=__return_value_ptr_copy, src=x.b, len=x.b_len)
# Create a reference to c as felt*.
let __return_value_tmp : felt* = cast(&c, felt*)
# Create a reference to x.c as felt*.
let __return_value_tmp : felt* = cast(&x.c, felt*)
assert [__return_value_ptr + 0] = [__return_value_tmp + 0]
assert [__return_value_ptr + 1] = [__return_value_tmp + 1]
assert [__return_value_ptr + 2] = [__return_value_tmp + 2]
Expand Down
Loading

0 comments on commit f464ec4

Please sign in to comment.