Skip to content

Commit

Permalink
Cairo v0.6.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
liorgold2 committed Nov 17, 2021
1 parent 577d7a5 commit 7712b21
Show file tree
Hide file tree
Showing 108 changed files with 2,735 additions and 1,432 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.5.2.zip .
> docker cp ${container_id}:/app/cairo-lang-0.6.0.zip .
> docker rm -v ${container_id}
```

3 changes: 1 addition & 2 deletions src/cmake_utils/gen_python_exe.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ def main():
source ${{BUILD_ROOT}}/{venv_dir_rel}/bin/activate
{args.environment_variables} \
CMAKE_TARGET_NAME={args.name} \
${{BUILD_ROOT}}/{venv_dir_rel}/bin/python -u -m {args.module} \
{exe_args} $@
${{BUILD_ROOT}}/{venv_dir_rel}/bin/python -u -m {args.module} {exe_args} "$@"
"""
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def add_class(self, cls: type):
self.classes[cls_name] = cls


class EverestTransactionExecutionInfo(ValidatedMarshmallowDataclass):
class EverestTransactionExecutionInfo:
"""
Base class of classes containing information generated from an execution of a transaction on
the state. Each Everest application may implement it specifically.
Expand Down
1 change: 1 addition & 0 deletions src/services/everest/definitions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ python_lib(everest_definitions_lib
fields.py

LIBS
starkware_crypto_lib
starkware_dataclasses_utils_lib
starkware_error_handling_lib
pip_marshmallow
Expand Down
41 changes: 25 additions & 16 deletions src/services/everest/definitions/fields.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import dataclasses
import random
import string
from typing import List, Optional
from typing import Any, ClassVar, Dict, List, Optional

import marshmallow.fields as mfields
from eth_typing import ChecksumAddress
from web3 import Web3

from services.everest.definitions import constants
from starkware.crypto.signature.signature import FIELD_PRIME
from starkware.python.utils import initialize_random
from starkware.starkware_utils.error_handling import ErrorCode, StarkErrorCode
from starkware.starkware_utils.error_handling import StarkErrorCode
from starkware.starkware_utils.field_validators import validate_non_negative
from starkware.starkware_utils.validated_fields import Field, RangeValidatedField

Expand All @@ -27,13 +29,10 @@ class EthAddressTypeField(Field[str]):
A field representation of an Ethereum address.
"""

def __init__(self, name, error_code):
self._name = name
self._error_code = error_code
error_message: ClassVar[str] = "{name} {value} is out of range / not checksummed."

@property
def name(self) -> str:
return self._name
def __init__(self, name, error_code):
super().__init__(name, error_code)

# Randomization.
def get_random_value(self, random_object: Optional[random.Random] = None) -> str:
Expand All @@ -52,13 +51,11 @@ def get_invalid_values(self) -> List[str]:
self.get_random_value() + "0", # type: ignore # Too long address.
]

@property
def error_code(self) -> ErrorCode:
return self._error_code

def format_invalid_value_error_message(self, value: str, name: Optional[str] = None) -> str:
name = self.name if name is None else name
return f"{name} {value} is out of range / not checksummed."
return self.error_message.format(
name=self.name if name is None else name,
value=value,
)

# Serialization.
def get_marshmallow_field(self) -> mfields.Field:
Expand All @@ -85,6 +82,18 @@ def format(self, value: str) -> str:
EthAddressIntField = RangeValidatedField(
lower_bound=constants.ETH_ADDRESS_LOWER_BOUND,
upper_bound=constants.ETH_ADDRESS_UPPER_BOUND,
name_in_error_message="Ethereum address",
out_of_range_error_code=StarkErrorCode.OUT_OF_RANGE_ETH_ADDRESS,
name="Ethereum address",
error_code=StarkErrorCode.OUT_OF_RANGE_ETH_ADDRESS,
)

FeltField = RangeValidatedField(
lower_bound=0,
upper_bound=FIELD_PRIME,
name="Field element",
error_code=StarkErrorCode.OUT_OF_RANGE_FIELD_ELEMENT,
formatter=hex,
)


def felt_metadata(name_in_error_message: str) -> Dict[str, Any]:
return dataclasses.replace(FeltField, name=name_in_error_message).metadata()
2 changes: 2 additions & 0 deletions src/starkware/cairo/bootloader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ python_lib(cairo_hash_program_lib
cairo_compile_lib
cairo_version_lib
cairo_vm_crypto_lib
starkware_python_utils_lib
)

python_venv(cairo_hash_program_venv
Expand Down Expand Up @@ -43,6 +44,7 @@ python_lib(cairo_bootloader_generate_fact_lib
cairo_hash_program_lib
cairo_relocatable_lib
cairo_vm_lib
starkware_python_utils_lib
pip_eth_hash
pip_pycryptodome
)
7 changes: 4 additions & 3 deletions src/starkware/cairo/bootloader/compute_fact.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from eth_hash.auto import keccak

from starkware.cairo.bootloader.fact_topology import FactTopology
from starkware.python.utils import to_bytes


def keccak_ints(values: List[int]) -> str:
Expand All @@ -13,9 +14,9 @@ def keccak_ints(values: List[int]) -> str:
This function is compatible with
Web3.solidityKeccak(['uint256[]'], [values]).hex()
"""
return "0x" + binascii.hexlify(
keccak(b"".join(value.to_bytes(32, "big") for value in values))
).decode("ascii")
return "0x" + binascii.hexlify(keccak(b"".join(to_bytes(value) for value in values))).decode(
"ascii"
)


def generate_program_fact(
Expand Down
3 changes: 2 additions & 1 deletion src/starkware/cairo/bootloader/hash_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
from starkware.cairo.lang.compiler.program import Program, ProgramBase
from starkware.cairo.lang.version import __version__
from starkware.cairo.lang.vm.crypto import get_crypto_lib_context_manager
from starkware.python.utils import from_bytes


def compute_program_hash_chain(program: ProgramBase, bootloader_version=0):
"""
Computes a hash chain over a program, including the length of the data chain.
"""
builtin_list = [int.from_bytes(builtin.encode("ascii"), "big") for builtin in program.builtins]
builtin_list = [from_bytes(builtin.encode("ascii")) for builtin in program.builtins]
# The program header below is missing the data length, which is later added to the data_chain.
program_header = [bootloader_version, program.main, len(program.builtins)] + builtin_list
data_chain = program_header + program.data
Expand Down
1 change: 1 addition & 0 deletions src/starkware/cairo/builtin_selection/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ full_python_test(cairo_builtin_selection_test
cairo_test_utils
cairo_vm_lib
starkware_crypto_lib
starkware_python_utils_lib
pip_pytest
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from starkware.cairo.common.test_utils import create_memory_struct
from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME
from starkware.cairo.lang.vm.cairo_runner import CairoRunner
from starkware.python.utils import from_bytes


@pytest.mark.parametrize(
Expand Down Expand Up @@ -34,7 +35,7 @@ def test_select_input_builtins(builtin_selection_indicators):

# Setup function.
builtins_encoding = {
builtin: int.from_bytes(builtin.encode("ascii"), "big")
builtin: from_bytes(builtin.encode("ascii"))
for builtin in ["output", "pedersen", "range_check", "ecdsa", "bitwise"]
}
all_builtins = [output_base, hash_base, range_check_base, signature_base, bitwise_base]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME
from starkware.cairo.lang.instances import small_instance
from starkware.cairo.lang.vm.cairo_runner import CairoRunner
from starkware.cairo.lang.vm.vm import VmException
from starkware.cairo.lang.vm.vm_exceptions import VmException

CAIRO_FILE = os.path.join(os.path.dirname(__file__), "validate_builtins.cairo")

Expand Down
2 changes: 1 addition & 1 deletion src/starkware/cairo/common/cairo_function_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from starkware.cairo.lang.vm.relocatable import MaybeRelocatable, RelocatableValue
from starkware.cairo.lang.vm.security import SecurityError, verify_secure_runner
from starkware.cairo.lang.vm.utils import RunResources
from starkware.cairo.lang.vm.vm import VmException
from starkware.cairo.lang.vm.vm_exceptions import VmException


class CairoFunctionRunner(CairoRunner):
Expand Down
150 changes: 91 additions & 59 deletions src/starkware/cairo/common/cairo_keccak/keccak_utils.py
Original file line number Diff line number Diff line change
@@ -1,80 +1,112 @@
from typing import List
# Implementation of Keccak-f[u*u*w], as defined in https://en.wikipedia.org/wiki/SHA-3.

OFFSETS = list(
zip(
*[
[0, 1, 62, 28, 27],
[36, 44, 6, 55, 20],
[3, 10, 43, 25, 39],
[41, 45, 15, 21, 8],
[18, 2, 61, 56, 14],
]
)
)
import operator
from functools import reduce
from typing import Iterable, List, Optional

ROUND_CONSTANTS = [
0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
]
from starkware.python.math_utils import div_ceil
from starkware.python.utils import from_bytes, to_bytes


def rot_left(x, n):
def rot_left(x, n, w):
"""
Rotates a 64-bit number n bits to the left.
Rotates a w-bit number n bits to the left.
"""
return ((x << n) & (2 ** 64 - 1)) | (x >> (64 - n))
return ((x << n) & (2 ** w - 1)) | (x >> (w - n))


def precompute_offsets(w: int, u: int, alpha: int, beta: int) -> List[List[int]]:
x, y = 1, 0
xy_pairs = set()
offset = 0
result = [[0] * u for _ in range(u)]
for t in range(1, u ** 2):
xy_pairs.add((x, y))
offset = (offset + t) % w
result[x][y] = offset
# The official definition is (alpha, beta) = (3, 2) for u = 5. Any other u has no official
# definition, but the iteration must go over each (x, y) != (0, 0) pair exactly once.
x, y = y, (beta * x + alpha * y) % u
assert len(xy_pairs) == u ** 2 - 1
return result


def keccak_round(a: List[List[int]], rc: int) -> List[List[int]]:
def precompute_rc(ell: int, rounds: Optional[int] = None) -> Iterable[int]:
x = 1
if rounds is None:
rounds = 12 + 2 * ell
for _ in range(rounds):
rc = 0
for m in range(ell + 1):
rc += (x & 1) << (2 ** m - 1)
x <<= 1
x ^= 0x171 * (x >> 8)
yield rc


def keccak_round(
a: List[List[int]], offsets: List[List[int]], rc: int, w: int, u: int, alpha: int, beta: int
) -> List[List[int]]:
"""
Performs one keccak round on a matrix of 5x5 64-bit integers.
Performs one keccak round on a matrix of uxu w-bit integers.
rc is the round constant.
"""
c = [a[x][0] ^ a[x][1] ^ a[x][2] ^ a[x][3] ^ a[x][4] for x in range(5)]
d = [c[(x - 1) % 5] ^ rot_left(c[(x + 1) % 5], 1) for x in range(5)]
a = [[a[x][y] ^ d[x] for y in range(5)] for x in range(5)]
b = [[0] * 5 for _ in range(5)]
for x in range(5):
for y in range(5):
b[y][(2 * x + 3 * y) % 5] = rot_left(a[x][y], OFFSETS[x][y])

a = [[b[x][y] ^ ((~b[(x + 1) % 5][y]) & b[(x + 2) % 5][y]) for y in range(5)] for x in range(5)]

c = [reduce(operator.xor, a[x]) for x in range(u)]
d = [c[(x - 1) % u] ^ rot_left(c[(x + 1) % u], 1, w) for x in range(u)]
a = [[a[x][y] ^ d[x] for y in range(u)] for x in range(u)]
b = [a[x][:] for x in range(u)]
for x in range(u):
for y in range(u):
b[y][(beta * x + alpha * y) % u] = rot_left(a[x][y], offsets[x][y], w)
a = [[b[x][y] ^ ((~b[(x + 1) % u][y]) & b[(x + 2) % u][y]) for y in range(u)] for x in range(u)]
a[0][0] ^= rc
return a


def keccak_func(values: List[int]) -> List[int]:
def keccak_func(
values: List[int],
ell: int = 6,
u: int = 5,
alpha: int = 3,
beta: int = 2,
rounds: Optional[int] = None,
) -> List[int]:
"""
Computes the keccak block permutation on 25 64-bit integers.
Computes the keccak block permutation on u**2 2**ell-bit integers.
"""
# Reshape values to a matrix.
value_matrix = [[values[5 * y + x] for y in range(5)] for x in range(5)]
for rc in ROUND_CONSTANTS:
value_matrix = keccak_round(value_matrix, rc)
value_matrix = [[values[u * y + x] for y in range(u)] for x in range(u)]
w = 2 ** ell
offsets = precompute_offsets(w, u, alpha, beta)
for rc in precompute_rc(ell, rounds):
value_matrix = keccak_round(
a=value_matrix, offsets=offsets, rc=rc, w=w, u=u, alpha=alpha, beta=beta
)
# Reshape values to a flat list.
values = [value_matrix[y][x] for x in range(5) for y in range(5)]
values = [value_matrix[y][x] for x in range(u) for y in range(u)]

return values


def keccak_f(
message: bytes,
ell: int = 6,
u: int = 5,
alpha: int = 3,
beta: int = 2,
rounds: Optional[int] = None,
) -> bytes:
"""
Computes the keccak block permutation on a u**2*2**ell-bit message (pads with zeros).
"""
w = 2 ** ell
assert len(message) <= div_ceil(u * u * w, 8)
as_bigint = from_bytes(message, byte_order="little")
assert as_bigint < 2 ** (u * u * w)
as_integers = [(as_bigint >> (i * w)) & (2 ** w - 1) for i in range(u ** 2)]
result = keccak_func(values=as_integers, ell=ell, u=u, alpha=alpha, beta=beta, rounds=rounds)
return to_bytes(
sum(x << (i * w) for i, x in enumerate(result)),
length=(u ** 2 * w + 7) // 8,
byte_order="little",
)
1 change: 1 addition & 0 deletions src/starkware/cairo/common/keccak.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func unsafe_keccak(data : felt*, length : felt) -> (low, high):
local high
%{
from eth_hash.auto import keccak

data, length = ids.data, ids.length

if '__keccak_max_size' in globals():
Expand Down
Loading

0 comments on commit 7712b21

Please sign in to comment.