From 8eb95584679afef5ad26b98bf32c18bc30d4fe28 Mon Sep 17 00:00:00 2001 From: Lior Goldberg Date: Sun, 28 Nov 2021 18:49:00 +0200 Subject: [PATCH] Cairo v0.6.1. --- README.md | 2 +- scripts/requirements-deps.json | 172 +++++++++++------- scripts/requirements-gen.txt | 2 +- scripts/requirements.txt | 51 +++--- src/starkware/cairo/bootloader/CMakeLists.txt | 4 + src/starkware/cairo/bootloader/__init__.py | 0 .../bootloader/bootloader_test_utils.cmake | 9 + .../bootloader/program_hash_test_utils.py | 33 ++++ src/starkware/cairo/lang/VERSION | 2 +- .../cairo/lang/ide/vscode-cairo/package.json | 2 +- src/starkware/cairo/lang/lang.cmake | 1 + src/starkware/starknet/cli/starknet_cli.py | 120 +++++++----- src/starkware/starknet/core/os/CMakeLists.txt | 17 ++ .../starknet/core/os/program_hash.json | 1 + .../starknet/core/os/program_hash_test.py | 21 +++ .../starknet/definitions/error_codes.py | 1 + src/starkware/starknet/definitions/fields.py | 6 +- .../feeder_gateway/feeder_gateway_client.py | 34 ++++ 18 files changed, 340 insertions(+), 138 deletions(-) create mode 100644 src/starkware/cairo/bootloader/__init__.py create mode 100644 src/starkware/cairo/bootloader/bootloader_test_utils.cmake create mode 100644 src/starkware/cairo/bootloader/program_hash_test_utils.py create mode 100644 src/starkware/starknet/core/os/program_hash.json create mode 100644 src/starkware/starknet/core/os/program_hash_test.py diff --git a/README.md b/README.md index 7ab18f48..6acbceec 100644 --- a/README.md +++ b/README.md @@ -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.6.0.zip . +> docker cp ${container_id}:/app/cairo-lang-0.6.1.zip . > docker rm -v ${container_id} ``` diff --git a/scripts/requirements-deps.json b/scripts/requirements-deps.json index 3b396b69..04cbe9a1 100644 --- a/scripts/requirements-deps.json +++ b/scripts/requirements-deps.json @@ -2,7 +2,7 @@ { "dependencies": [], "package": { - "installed_version": "5.3.1", + "installed_version": "6.0", "key": "pyyaml", "package_name": "PyYAML" } @@ -10,10 +10,22 @@ { "dependencies": [ { - "installed_version": "3.0.1", + "installed_version": "1.2.0", + "key": "aiosignal", + "package_name": "aiosignal", + "required_version": ">=1.1.2" + }, + { + "installed_version": "4.0.1", "key": "async-timeout", "package_name": "async-timeout", - "required_version": ">=3.0,<4.0" + "required_version": ">=4.0.0a3,<5.0" + }, + { + "installed_version": "0.13.0", + "key": "asynctest", + "package_name": "asynctest", + "required_version": "==0.13.0" }, { "installed_version": "21.2.0", @@ -22,10 +34,16 @@ "required_version": ">=17.3.0" }, { - "installed_version": "4.0.0", - "key": "chardet", - "package_name": "chardet", - "required_version": ">=2.0,<5.0" + "installed_version": "2.0.8", + "key": "charset-normalizer", + "package_name": "charset-normalizer", + "required_version": ">=2.0,<3.0" + }, + { + "installed_version": "1.2.0", + "key": "frozenlist", + "package_name": "frozenlist", + "required_version": ">=1.1.1" }, { "installed_version": "5.2.0", @@ -37,29 +55,59 @@ "installed_version": "3.10.0.2", "key": "typing-extensions", "package_name": "typing-extensions", - "required_version": ">=3.6.5" + "required_version": ">=3.7.4" }, { - "installed_version": "1.7.0", + "installed_version": "1.7.2", "key": "yarl", "package_name": "yarl", "required_version": ">=1.0,<2.0" } ], "package": { - "installed_version": "3.7.4.post0", + "installed_version": "3.8.1", "key": "aiohttp", "package_name": "aiohttp" } }, { - "dependencies": [], + "dependencies": [ + { + "installed_version": "1.2.0", + "key": "frozenlist", + "package_name": "frozenlist", + "required_version": ">=1.1.0" + } + ], "package": { - "installed_version": "3.0.1", + "installed_version": "1.2.0", + "key": "aiosignal", + "package_name": "aiosignal" + } + }, + { + "dependencies": [ + { + "installed_version": "3.10.0.2", + "key": "typing-extensions", + "package_name": "typing-extensions", + "required_version": ">=3.6.5" + } + ], + "package": { + "installed_version": "4.0.1", "key": "async-timeout", "package_name": "async-timeout" } }, + { + "dependencies": [], + "package": { + "installed_version": "0.13.0", + "key": "asynctest", + "package_name": "asynctest" + } + }, { "dependencies": [], "package": { @@ -71,7 +119,7 @@ { "dependencies": [], "package": { - "installed_version": "2.1.0", + "installed_version": "2.1.1", "key": "base58", "package_name": "base58" } @@ -103,15 +151,7 @@ { "dependencies": [], "package": { - "installed_version": "4.0.0", - "key": "chardet", - "package_name": "chardet" - } - }, - { - "dependencies": [], - "package": { - "installed_version": "2.0.6", + "installed_version": "2.0.8", "key": "charset-normalizer", "package_name": "charset-normalizer" } @@ -119,14 +159,14 @@ { "dependencies": [ { - "installed_version": "0.11.1", + "installed_version": "0.11.2", "key": "toolz", "package_name": "toolz", "required_version": ">=0.8.0" } ], "package": { - "installed_version": "0.11.0", + "installed_version": "0.11.2", "key": "cytoolz", "package_name": "cytoolz" } @@ -241,7 +281,7 @@ { "dependencies": [ { - "installed_version": "0.11.0", + "installed_version": "0.11.2", "key": "cytoolz", "package_name": "cytoolz", "required_version": ">=0.9.0,<1.0.0" @@ -330,7 +370,7 @@ { "dependencies": [ { - "installed_version": "0.11.0", + "installed_version": "0.11.2", "key": "cytoolz", "package_name": "cytoolz", "required_version": ">=0.10.1,<1.0.0" @@ -357,7 +397,7 @@ { "dependencies": [], "package": { - "installed_version": "2.2.1", + "installed_version": "2.2.3", "key": "fastecdsa", "package_name": "fastecdsa" } @@ -370,6 +410,14 @@ "package_name": "frozendict" } }, + { + "dependencies": [], + "package": { + "installed_version": "1.2.0", + "key": "frozenlist", + "package_name": "frozenlist" + } + }, { "dependencies": [], "package": { @@ -381,7 +429,7 @@ { "dependencies": [], "package": { - "installed_version": "3.2", + "installed_version": "3.3", "key": "idna", "package_name": "idna" } @@ -402,7 +450,7 @@ } ], "package": { - "installed_version": "4.8.1", + "installed_version": "4.8.2", "key": "importlib-metadata", "package_name": "importlib-metadata" } @@ -445,7 +493,7 @@ "required_version": ">=17.4.0" }, { - "installed_version": "4.8.1", + "installed_version": "4.8.2", "key": "importlib-metadata", "package_name": "importlib-metadata", "required_version": null @@ -457,7 +505,7 @@ "required_version": ">=0.14.0" }, { - "installed_version": "58.1.0", + "installed_version": "58.4.0", "key": "setuptools", "package_name": "setuptools", "required_version": null @@ -494,7 +542,7 @@ { "dependencies": [], "package": { - "installed_version": "3.13.0", + "installed_version": "3.14.1", "key": "marshmallow", "package_name": "marshmallow" } @@ -502,7 +550,7 @@ { "dependencies": [ { - "installed_version": "3.13.0", + "installed_version": "3.14.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=3.13.0,<4.0" @@ -523,7 +571,7 @@ { "dependencies": [ { - "installed_version": "3.13.0", + "installed_version": "3.14.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=2.0.0" @@ -538,7 +586,7 @@ { "dependencies": [ { - "installed_version": "3.13.0", + "installed_version": "3.14.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=3.0.0,<4.0.0" @@ -561,7 +609,7 @@ { "dependencies": [ { - "installed_version": "2.1.0", + "installed_version": "2.1.1", "key": "base58", "package_name": "base58", "required_version": null @@ -618,7 +666,7 @@ { "dependencies": [], "package": { - "installed_version": "1.21.2", + "installed_version": "1.21.4", "key": "numpy", "package_name": "numpy" } @@ -626,14 +674,14 @@ { "dependencies": [ { - "installed_version": "2.4.7", + "installed_version": "3.0.6", "key": "pyparsing", "package_name": "pyparsing", - "required_version": ">=2.0.2" + "required_version": ">=2.0.2,!=3.0.5" } ], "package": { - "installed_version": "21.0", + "installed_version": "21.3", "key": "packaging", "package_name": "packaging" } @@ -656,7 +704,7 @@ { "dependencies": [], "package": { - "installed_version": "21.2.4", + "installed_version": "21.3.1", "key": "pip", "package_name": "pip" } @@ -664,14 +712,14 @@ { "dependencies": [ { - "installed_version": "21.2.4", + "installed_version": "21.3.1", "key": "pip", "package_name": "pip", "required_version": ">=6.0.0" } ], "package": { - "installed_version": "2.1.0", + "installed_version": "2.2.0", "key": "pipdeptree", "package_name": "pipdeptree" } @@ -679,7 +727,7 @@ { "dependencies": [ { - "installed_version": "4.8.1", + "installed_version": "4.8.2", "key": "importlib-metadata", "package_name": "importlib-metadata", "required_version": ">=0.12" @@ -694,7 +742,7 @@ { "dependencies": [], "package": { - "installed_version": "0.11.0", + "installed_version": "0.12.0", "key": "prometheus-client", "package_name": "prometheus-client" } @@ -702,7 +750,7 @@ { "dependencies": [], "package": { - "installed_version": "3.18.1", + "installed_version": "3.19.1", "key": "protobuf", "package_name": "protobuf" } @@ -710,7 +758,7 @@ { "dependencies": [], "package": { - "installed_version": "1.10.0", + "installed_version": "1.11.0", "key": "py", "package_name": "py" } @@ -726,7 +774,7 @@ { "dependencies": [], "package": { - "installed_version": "2.4.7", + "installed_version": "3.0.6", "key": "pyparsing", "package_name": "pyparsing" } @@ -748,7 +796,7 @@ "required_version": ">=19.2.0" }, { - "installed_version": "4.8.1", + "installed_version": "4.8.2", "key": "importlib-metadata", "package_name": "importlib-metadata", "required_version": ">=0.12" @@ -760,7 +808,7 @@ "required_version": null }, { - "installed_version": "21.0", + "installed_version": "21.3", "key": "packaging", "package_name": "packaging", "required_version": null @@ -772,7 +820,7 @@ "required_version": ">=0.12,<2.0" }, { - "installed_version": "1.10.0", + "installed_version": "1.11.0", "key": "py", "package_name": "py", "required_version": ">=1.8.2" @@ -800,7 +848,7 @@ } ], "package": { - "installed_version": "0.15.1", + "installed_version": "0.16.0", "key": "pytest-asyncio", "package_name": "pytest-asyncio" } @@ -814,13 +862,13 @@ "required_version": ">=2017.4.17" }, { - "installed_version": "2.0.6", + "installed_version": "2.0.8", "key": "charset-normalizer", "package_name": "charset-normalizer", "required_version": "~=2.0.0" }, { - "installed_version": "3.2", + "installed_version": "3.3", "key": "idna", "package_name": "idna", "required_version": ">=2.5,<4" @@ -856,7 +904,7 @@ { "dependencies": [], "package": { - "installed_version": "58.1.0", + "installed_version": "58.4.0", "key": "setuptools", "package_name": "setuptools" } @@ -895,7 +943,7 @@ { "dependencies": [], "package": { - "installed_version": "0.11.1", + "installed_version": "0.11.2", "key": "toolz", "package_name": "toolz" } @@ -903,7 +951,7 @@ { "dependencies": [], "package": { - "installed_version": "2.12.1", + "installed_version": "2.13.2", "key": "typeguard", "package_name": "typeguard" } @@ -956,7 +1004,7 @@ { "dependencies": [ { - "installed_version": "3.7.4.post0", + "installed_version": "3.8.1", "key": "aiohttp", "package_name": "aiohttp", "required_version": ">=3.7.4.post0,<4" @@ -1016,7 +1064,7 @@ "required_version": ">=1.1.6,<2.0.0" }, { - "installed_version": "3.18.1", + "installed_version": "3.19.1", "key": "protobuf", "package_name": "protobuf", "required_version": ">=3.10.0,<4" @@ -1041,7 +1089,7 @@ } ], "package": { - "installed_version": "5.24.0", + "installed_version": "5.25.0", "key": "web3", "package_name": "web3" } @@ -1065,7 +1113,7 @@ { "dependencies": [ { - "installed_version": "3.2", + "installed_version": "3.3", "key": "idna", "package_name": "idna", "required_version": ">=2.0" @@ -1084,7 +1132,7 @@ } ], "package": { - "installed_version": "1.7.0", + "installed_version": "1.7.2", "key": "yarl", "package_name": "yarl" } diff --git a/scripts/requirements-gen.txt b/scripts/requirements-gen.txt index 18baa9fc..f8fe93a0 100644 --- a/scripts/requirements-gen.txt +++ b/scripts/requirements-gen.txt @@ -15,7 +15,7 @@ pipdeptree prometheus-client pytest pytest-asyncio -PyYAML>=5.3.1,<5.4 +PyYAML sympy typeguard Web3 diff --git a/scripts/requirements.txt b/scripts/requirements.txt index 93b5e085..cb2114f1 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,15 +1,16 @@ # This file is autogenerated. Do not edit manually. -aiohttp==3.7.4.post0 -async-timeout==3.0.1 +aiohttp==3.8.1 +aiosignal==1.2.0 +async-timeout==4.0.1 +asynctest==0.13.0 attrs==21.2.0 -base58==2.1.0 +base58==2.1.1 bitarray==1.2.2 cachetools==4.2.4 certifi==2021.10.8 -chardet==4.0.0 -charset-normalizer==2.0.6 -cytoolz==0.11.0 +charset-normalizer==2.0.8 +cytoolz==0.11.2 ecdsa==0.17.0 eth-abi==2.1.1 eth-account==0.5.6 @@ -19,17 +20,18 @@ eth-keys==0.3.3 eth-rlp==0.2.1 eth-typing==2.2.2 eth-utils==1.9.5 -fastecdsa==2.2.1 +fastecdsa==2.2.3 frozendict==1.2 +frozenlist==1.2.0 hexbytes==0.2.2 -idna==3.2 -importlib-metadata==4.8.1 +idna==3.3 +importlib-metadata==4.8.2 iniconfig==1.1.1 ipfshttpclient==0.8.0a2 jsonschema==3.2.0 lark-parser==0.12.0 lru-dict==1.1.7 -marshmallow==3.13.0 +marshmallow==3.14.1 marshmallow-dataclass==8.5.3 marshmallow-enum==1.5.1 marshmallow-oneofschema==3.0.1 @@ -38,32 +40,35 @@ multiaddr==0.0.9 multidict==5.2.0 mypy-extensions==0.4.3 netaddr==0.8.0 -numpy==1.21.2 -packaging==21.0 +numpy==1.21.4 +packaging==21.3 parsimonious==0.8.1 -pipdeptree==2.1.0 +pip==21.3.1 +pipdeptree==2.2.0 pluggy==1.0.0 -prometheus-client==0.11.0 -protobuf==3.18.1 -py==1.10.0 +prometheus-client==0.12.0 +protobuf==3.19.1 +py==1.11.0 pycryptodome==3.11.0 -pyparsing==2.4.7 +pyparsing==3.0.6 pyrsistent==0.18.0 pytest==6.2.5 -pytest-asyncio==0.15.1 -PyYAML==5.3.1 +pytest-asyncio==0.16.0 +PyYAML==6.0 requests==2.26.0 rlp==2.0.1 +setuptools==58.4.0 six==1.16.0 sympy==1.9 toml==0.10.2 -toolz==0.11.1 -typeguard==2.12.1 +toolz==0.11.2 +typeguard==2.13.2 typing-extensions==3.10.0.2 typing-inspect==0.7.1 urllib3==1.26.7 varint==1.0.2 -web3==5.24.0 +web3==5.25.0 websockets==9.1 -yarl==1.7.0 +wheel==0.37.0 +yarl==1.7.2 zipp==3.6.0 diff --git a/src/starkware/cairo/bootloader/CMakeLists.txt b/src/starkware/cairo/bootloader/CMakeLists.txt index b063521e..dcf0aeb1 100644 --- a/src/starkware/cairo/bootloader/CMakeLists.txt +++ b/src/starkware/cairo/bootloader/CMakeLists.txt @@ -1,3 +1,7 @@ +set(PROGRAM_HASH_TEST_UTILS_LIB_ADDITIONAL_LIBS cairo_hash_program_lib) + +include(bootloader_test_utils.cmake) + python_lib(cairo_hash_program_lib PREFIX starkware/cairo/bootloader diff --git a/src/starkware/cairo/bootloader/__init__.py b/src/starkware/cairo/bootloader/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/cairo/bootloader/bootloader_test_utils.cmake b/src/starkware/cairo/bootloader/bootloader_test_utils.cmake new file mode 100644 index 00000000..69b83034 --- /dev/null +++ b/src/starkware/cairo/bootloader/bootloader_test_utils.cmake @@ -0,0 +1,9 @@ +python_lib(program_hash_test_utils_lib + PREFIX starkware/cairo/bootloader + + FILES + program_hash_test_utils.py + + LIBS + ${PROGRAM_HASH_TEST_UTILS_LIB_ADDITIONAL_LIBS} +) diff --git a/src/starkware/cairo/bootloader/program_hash_test_utils.py b/src/starkware/cairo/bootloader/program_hash_test_utils.py new file mode 100644 index 00000000..bfe36eb7 --- /dev/null +++ b/src/starkware/cairo/bootloader/program_hash_test_utils.py @@ -0,0 +1,33 @@ +import json + +from starkware.cairo.bootloader.hash_program import compute_program_hash_chain +from starkware.cairo.lang.compiler.program import Program + + +def run_generate_hash_test(fix: bool, program_path: str, hash_path: str, command: str): + compiled_program = Program.Schema().load(json.load(open(program_path))) + program_hash = hex(compute_program_hash_chain(program=compiled_program)) + program_hash_key = "program_hash" + + if fix: + with open(hash_path, "w") as fp: + json.dump({program_hash_key: program_hash}, fp=fp) + return + + expected_hash = json.load(open(hash_path))[program_hash_key] + assert expected_hash == program_hash, ( + f"Wrong program hash in program_hash.json. Found: {program_hash}. " + f"Expected: {expected_hash}. Please run {command}." + ) + + +def program_hash_test_main(program_path: str, hash_path: str, command: str): + import argparse + + parser = argparse.ArgumentParser(description="Create or test the program hash.") + parser.add_argument("--fix", action="store_true", help="Fix the value of the program hash.") + + args = parser.parse_args() + run_generate_hash_test( + fix=args.fix, program_path=program_path, hash_path=hash_path, command=command + ) diff --git a/src/starkware/cairo/lang/VERSION b/src/starkware/cairo/lang/VERSION index a918a2aa..ee6cdce3 100644 --- a/src/starkware/cairo/lang/VERSION +++ b/src/starkware/cairo/lang/VERSION @@ -1 +1 @@ -0.6.0 +0.6.1 diff --git a/src/starkware/cairo/lang/ide/vscode-cairo/package.json b/src/starkware/cairo/lang/ide/vscode-cairo/package.json index 1632dd22..3701b8ba 100644 --- a/src/starkware/cairo/lang/ide/vscode-cairo/package.json +++ b/src/starkware/cairo/lang/ide/vscode-cairo/package.json @@ -2,7 +2,7 @@ "name": "cairo", "displayName": "Cairo", "description": "Support Cairo syntax", - "version": "0.6.0", + "version": "0.6.1", "engines": { "vscode": "^1.30.0" }, diff --git a/src/starkware/cairo/lang/lang.cmake b/src/starkware/cairo/lang/lang.cmake index e294bb0f..8103e541 100644 --- a/src/starkware/cairo/lang/lang.cmake +++ b/src/starkware/cairo/lang/lang.cmake @@ -31,6 +31,7 @@ python_venv(cairo_lang_package_venv cairo_hash_program_lib cairo_run_lib cairo_script_lib + program_hash_test_utils_lib sharp_client_config_lib sharp_client_lib starknet_script_lib diff --git a/src/starkware/starknet/cli/starknet_cli.py b/src/starkware/starknet/cli/starknet_cli.py index 9356379c..28a72acf 100755 --- a/src/starkware/starknet/cli/starknet_cli.py +++ b/src/starkware/starknet/cli/starknet_cli.py @@ -6,11 +6,12 @@ import json import os import sys -from typing import List +from typing import Any, Dict, List from services.everest.definitions import fields as everest_fields from services.external_api.base_client import RetryConfig from starkware.cairo.lang.compiler.ast.cairo_types import TypeFelt, TypePointer +from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager from starkware.cairo.lang.compiler.parser import parse_type from starkware.cairo.lang.compiler.program import Program from starkware.cairo.lang.compiler.type_system import mark_type_resolved @@ -27,6 +28,11 @@ from starkware.starknet.services.api.gateway.transaction import Deploy, InvokeFunction from starkware.starkware_utils.error_handling import StarkErrorCode +NETWORKS = { + "alpha": "alpha4.starknet.io", + "alpha-mainnet": "alpha-mainnet.starknet.io", +} + def felt_formatter(hex_felt: str) -> str: return field_element_repr(val=int(hex_felt, 16), prime=everest_fields.FeltField.upper_bound) @@ -60,6 +66,48 @@ def get_feeder_gateway_client(args) -> FeederGatewayClient: return FeederGatewayClient(url=feeder_gateway_url, retry_config=retry_config) +def parse_inputs(values: List[str]) -> List[int]: + result = [] + for value in values: + try: + result.append(int(value, 16) if value.startswith("0x") else int(value)) + except ValueError: + raise ValueError( + f"Invalid input value: '{value}'. Expected a decimal or hexadecimal integer." + ) + return result + + +def validate_arguments( + inputs: List[int], abi_entry: Dict[str, Any], identifier_manager: IdentifierManager +): + previous_felt_input = None + current_inputs_ptr = 0 + for input_desc in abi_entry["inputs"]: + typ = mark_type_resolved(parse_type(input_desc["type"])) + typ_size = check_felts_only_type(cairo_type=typ, identifier_manager=identifier_manager) + if typ_size is not None: + assert current_inputs_ptr + typ_size <= len(inputs), ( + f"Expected at least {current_inputs_ptr + typ_size} inputs, " f"got {len(inputs)}." + ) + + current_inputs_ptr += typ_size + elif typ == TypePointer(pointee=TypeFelt()): + assert previous_felt_input is not None, ( + f'The array argument {input_desc["name"]} of type felt* must be preceded ' + "by a length argument of type felt." + ) + + current_inputs_ptr += previous_felt_input + else: + raise Exception(f'Type {input_desc["type"]} is not supported.') + previous_felt_input = inputs[current_inputs_ptr - 1] if typ == TypeFelt() else None + + assert ( + len(inputs) == current_inputs_ptr + ), f"Wrong number of arguments. Expected {current_inputs_ptr}, got {len(inputs)}." + + async def deploy(args, command_args): parser = argparse.ArgumentParser(description="Sends a deploy transaction to StarkNet.") parser.add_argument( @@ -101,6 +149,19 @@ async def deploy(args, command_args): raise ValueError("Invalid salt format.") contract_definition = ContractDefinition.loads(args.contract.read()) + abi = contract_definition.abi + assert abi is not None, "Missing ABI in the given contract definition." + + for abi_entry in abi: + if abi_entry["type"] == "constructor": + validate_arguments( + inputs=inputs, + abi_entry=abi_entry, + identifier_manager=identifier_manager_from_abi(abi=abi), + ) + break + else: + assert len(inputs) == 0, "--inputs cannot be specified for contracts without a constructor." tx = Deploy( contract_address_salt=salt, @@ -122,18 +183,6 @@ async def deploy(args, command_args): ) -def parse_inputs(values: List[str]) -> List[int]: - result = [] - for value in values: - try: - result.append(int(value, 16) if value.startswith("0x") else int(value)) - except ValueError: - raise ValueError( - f"Invalid input value: '{value}'. Expected a decimal or hexadecimal integer." - ) - return result - - async def invoke_or_call(args, command_args, call: bool): parser = argparse.ArgumentParser(description="Sends an invoke transaction to StarkNet.") parser.add_argument( @@ -167,9 +216,6 @@ async def invoke_or_call(args, command_args, call: bool): abi = json.load(args.abi) - # Load types. - identifier_manager = identifier_manager_from_abi(abi=abi) - assert args.address.startswith("0x"), f"The address must start with '0x'. Got: {args.address}." try: address = int(args.address, 16) @@ -177,37 +223,15 @@ async def invoke_or_call(args, command_args, call: bool): raise ValueError(f"Invalid address format: {args.address}.") for abi_entry in abi: if abi_entry["type"] == "function" and abi_entry["name"] == args.function: - previous_felt_input = None - current_inputs_ptr = 0 - for input_desc in abi_entry["inputs"]: - typ = mark_type_resolved(parse_type(input_desc["type"])) - typ_size = check_felts_only_type( - cairo_type=typ, identifier_manager=identifier_manager - ) - if typ_size is not None: - assert current_inputs_ptr + typ_size <= len(inputs), ( - f"Expected at least {current_inputs_ptr + typ_size} inputs, " - f"got {len(inputs)}." - ) - - current_inputs_ptr += typ_size - elif typ == TypePointer(pointee=TypeFelt()): - assert previous_felt_input is not None, ( - f'The array argument {input_desc["name"]} of type felt* must be preceded ' - "by a length argument of type felt." - ) - - current_inputs_ptr += previous_felt_input - else: - raise Exception(f'Type {input_desc["type"]} is not supported.') - previous_felt_input = inputs[current_inputs_ptr - 1] if typ == TypeFelt() else None + validate_arguments( + inputs=inputs, + abi_entry=abi_entry, + identifier_manager=identifier_manager_from_abi(abi=abi), + ) break else: raise Exception(f"Function {args.function} not found.") selector = get_selector_from_name(args.function) - assert ( - len(inputs) == current_inputs_ptr - ), f"Wrong number of arguments. Expected {current_inputs_ptr}, got {len(inputs)}." calldata = inputs tx = InvokeFunction( @@ -319,11 +343,15 @@ 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}'.", file=sys.stderr) + if network not in NETWORKS: + networks_str = ", ".join(NETWORKS.keys()) + print( + f"Unknown network '{network}'. Supported networks: {networks_str}.", + file=sys.stderr, + ) return 1 - dns = "alpha4.starknet.io" + dns = NETWORKS[network] if args.gateway_url is None: args.gateway_url = f"https://{dns}/gateway" diff --git a/src/starkware/starknet/core/os/CMakeLists.txt b/src/starkware/starknet/core/os/CMakeLists.txt index ff2096c4..b8e11c18 100644 --- a/src/starkware/starknet/core/os/CMakeLists.txt +++ b/src/starkware/starknet/core/os/CMakeLists.txt @@ -52,4 +52,21 @@ python_lib(starknet_os_utils_lib starkware_python_utils_lib pip_cachetools ) + add_dependencies(starknet_os_utils_lib starknet_os_program) + +full_python_test(starknet_os_program_hash_test + PREFIX starkware/starknet/core/os + PYTHON python3.7 + TESTED_MODULES starkware/starknet/core/os + + FILES + program_hash_test.py + + LIBS + cairo_hash_program_lib + program_hash_test_utils_lib + starknet_os_utils_lib + starkware_python_utils_lib + pip_pytest +) diff --git a/src/starkware/starknet/core/os/program_hash.json b/src/starkware/starknet/core/os/program_hash.json new file mode 100644 index 00000000..b850c633 --- /dev/null +++ b/src/starkware/starknet/core/os/program_hash.json @@ -0,0 +1 @@ +{"program_hash": "0x7b398b9a63f058d0b91f346e3ebfae8da092b08b182973a1325302ec0e44dd"} diff --git a/src/starkware/starknet/core/os/program_hash_test.py b/src/starkware/starknet/core/os/program_hash_test.py new file mode 100644 index 00000000..c8e7a9f9 --- /dev/null +++ b/src/starkware/starknet/core/os/program_hash_test.py @@ -0,0 +1,21 @@ +import os + +from starkware.cairo.bootloader.program_hash_test_utils import ( + program_hash_test_main, + run_generate_hash_test, +) +from starkware.python.utils import get_source_dir_path + +PROGRAM_PATH = os.path.join(os.path.dirname(__file__), "starknet_os_compiled.json") +HASH_PATH = get_source_dir_path("src/starkware/starknet/core/os/program_hash.json") +COMMAND = "generate_starknet_os_program_hash" + + +def test_starknet_program_hash(): + run_generate_hash_test( + fix=False, program_path=PROGRAM_PATH, hash_path=HASH_PATH, command=COMMAND + ) + + +if __name__ == "__main__": + program_hash_test_main(program_path=PROGRAM_PATH, hash_path=HASH_PATH, command=COMMAND) diff --git a/src/starkware/starknet/definitions/error_codes.py b/src/starkware/starknet/definitions/error_codes.py index 65357ec5..4152a07e 100644 --- a/src/starkware/starknet/definitions/error_codes.py +++ b/src/starkware/starknet/definitions/error_codes.py @@ -35,6 +35,7 @@ class StarknetErrorCode(ErrorCode): SECURITY_ERROR = auto() TRANSACTION_FAILED = auto() TRANSACTION_LIMIT_EXCEEDED = auto() + TRANSACTION_NOT_FOUND = auto() UNEXPECTED_FAILURE = auto() UNINITIALIZED_CONTRACT = auto() diff --git a/src/starkware/starknet/definitions/fields.py b/src/starkware/starknet/definitions/fields.py index 55f6760c..4f672635 100644 --- a/src/starkware/starknet/definitions/fields.py +++ b/src/starkware/starknet/definitions/fields.py @@ -22,12 +22,12 @@ # Fields data: validation data, dataclass metadata. -block_number_metadata = sequential_id_metadata(field_name="block number") +block_number_metadata = sequential_id_metadata(field_name="Block number") optional_block_number_metadata = sequential_id_metadata( - field_name="block number", required=False, allow_none=True + field_name="Block number", required=False, allow_none=True ) optional_transaction_index_metadata = sequential_id_metadata( - field_name="transaction index", required=False, allow_none=True + field_name="Transaction index", required=False, allow_none=True ) felt_list_metadata = dict( diff --git a/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py b/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py index a1e3f0c0..f272ff61 100644 --- a/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py +++ b/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py @@ -100,6 +100,40 @@ async def get_transaction_receipt( ) return json.loads(raw_response) + async def get_block_hash_by_id(self, block_id: int) -> str: + raw_response = await self._send_request( + send_method="GET", + uri=f"/get_block_hash_by_id?blockId={block_id}", + ) + return json.loads(raw_response) + + async def get_block_id_by_hash(self, block_hash: CastableToHash) -> int: + raw_response = await self._send_request( + send_method="GET", + uri=( + "/get_block_id_by_hash?" + f"blockHash={format_hash(hash_value=block_hash, hash_field=fields.BlockHashField)}" + ), + ) + return json.loads(raw_response) + + async def get_transaction_hash_by_id(self, tx_id: int) -> str: + raw_response = await self._send_request( + send_method="GET", + uri=f"/get_transaction_hash_by_id?transactionId={tx_id}", + ) + return json.loads(raw_response) + + async def get_transaction_id_by_hash(self, tx_hash: CastableToHash) -> int: + raw_response = await self._send_request( + send_method="GET", + uri=( + "/get_transaction_id_by_hash?transactionHash=" + f"{format_hash(hash_value=tx_hash, hash_field=fields.TransactionHashField)}" + ), + ) + return json.loads(raw_response) + def format_hash(hash_value: CastableToHash, hash_field: RangeValidatedField) -> str: if isinstance(hash_value, int):