diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 509fd7c18..d4cfaf1ea 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -3,6 +3,7 @@ name: Checks env: CAIRO_LANG_VERSION: "0.13.1" DEVNET_VERSION: "0.1.2" + DEVNET_SHA: 7e7dbb5 on: push: @@ -97,7 +98,7 @@ jobs: # ====================== CONTRACTS v2 ====================== # - name: Cache contracts v2 id: cache-contracts_v2 - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: starknet_py/tests/e2e/mock/contracts_v2/target key: ${{ runner.os }}-contracts-${{ hashFiles('starknet_py/tests/e2e/mock/contracts_v2') }} @@ -111,7 +112,7 @@ jobs: - name: Cache contracts v1 id: cache-contracts_v1 - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: starknet_py/tests/e2e/mock/contracts_v1/target key: ${{ runner.os }}-contracts-${{ hashFiles('starknet_py/tests/e2e/mock/contracts_v1') }} @@ -125,7 +126,7 @@ jobs: - name: Cache contracts v0 id: cache-contracts - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: starknet_py/tests/e2e/mock/contracts_compiled key: ${{ runner.os }}-contracts-${{ hashFiles('starknet_py/tests/e2e/mock/contracts', 'poetry.lock') }}-${{ env.CAIRO_LANG_VERSION }} @@ -358,11 +359,19 @@ jobs: # ====================== SETUP DEVNET ====================== # + - name: Cache devnet build + id: windows-devnet-cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}\starknet_py\tests\e2e\devnet\bin + key: ${{ runner.os }}-devnet-${{ env.DEVNET_SHA }} + - name: Install devnet + if: steps.windows-devnet-cache.outputs.cache-hit != 'true' run: | - $DEVNET_INSTALL_DIR = "$(git rev-parse --show-toplevel)/starknet_py/tests/e2e/devnet" - cargo install --git https://github.com/0xSpaceShard/starknet-devnet-rs.git --locked --rev 7e7dbb5 --root $DEVNET_INSTALL_DIR - + $DEVNET_INSTALL_DIR = "${{ github.workspace }}\starknet_py\tests\e2e\devnet" + cargo install --git https://github.com/0xSpaceShard/starknet-devnet-rs.git --locked --rev ${{ env.DEVNET_SHA }} --root $DEVNET_INSTALL_DIR + shell: pwsh # ====================== SETUP PYTHON ====================== # - name: Install poetry @@ -512,10 +521,19 @@ jobs: # ====================== SETUP DEVNET ====================== # + - name: Cache devnet build + id: windows-devnet-cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}\starknet_py\tests\e2e\devnet\bin + key: ${{ runner.os }}-devnet-${{ env.DEVNET_SHA }} + - name: Install devnet + if: steps.windows-devnet-cache.outputs.cache-hit != 'true' run: | - $DEVNET_INSTALL_DIR = "$(git rev-parse --show-toplevel)/starknet_py/tests/e2e/devnet" - cargo install --git https://github.com/0xSpaceShard/starknet-devnet-rs.git --locked --rev 7e7dbb5 --root $DEVNET_INSTALL_DIR + $DEVNET_INSTALL_DIR = "${{ github.workspace }}\starknet_py\tests\e2e\devnet" + cargo install --git https://github.com/0xSpaceShard/starknet-devnet-rs.git --locked --rev ${{ env.DEVNET_SHA }} --root $DEVNET_INSTALL_DIR + shell: pwsh # ====================== RUN TESTS ====================== # diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 9c13ed416..84fdf4c2b 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -1,5 +1,9 @@ name: Build wheels -on: workflow_dispatch + +on: + push: + tags: + - '*' jobs: build_sdist: diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index 4d63e4948..bd70fc916 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -1,6 +1,17 @@ Migration guide =============== +****************************** +0.24.1 Migration guide +****************************** +This version contains a quick fix to parsing ABI for Cairo v2 contracts. Due to new release of compiler, `u96` is now compiled to `BoundedInt` in ABI. + +0.24.1 Minor changes +-------------------- + +1. Fixed parsing ABI that contains `u96` data type. +2. Fixed `l1_address` deserialization in `L2toL1MessageSchema`. + ****************************** 0.24.0 Migration guide ****************************** diff --git a/pyproject.toml b/pyproject.toml index c9033c76d..19aaa7afe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "starknet-py" -version = "0.24.0" +version = "0.24.1" description = "A python SDK for Starknet" authors = ["Tomasz Rejowski ", "Jakub Ptak "] include = ["starknet_py", "starknet_py/utils/crypto/libcrypto_c_exports.*"] diff --git a/starknet_py/abi/v2/parser_test.py b/starknet_py/abi/v2/parser_test.py index 01bc111fd..63520d22b 100644 --- a/starknet_py/abi/v2/parser_test.py +++ b/starknet_py/abi/v2/parser_test.py @@ -1,8 +1,10 @@ import json +from typing import cast import pytest from starknet_py.abi.v2 import Abi, AbiParser +from starknet_py.cairo.data_types import UintType from starknet_py.tests.e2e.fixtures.misc import ContractVersion, load_contract @@ -31,3 +33,40 @@ def test_abi_parse(contract_name): parsed_abi = parser.parse() assert isinstance(parsed_abi, Abi) + + +def test_bounded_int_parse(): + abi_list = [ + { + "type": "struct", + "name": "core::circuit::u384", + "members": [ + { + "name": "limb0", + "type": "core::internal::BoundedInt::<0, 79228162514264337593543950335>", + }, + { + "name": "limb1", + "type": "core::internal::BoundedInt::<0, 79228162514264337593543950335>", + }, + { + "name": "limb2", + "type": "core::internal::BoundedInt::<0, 79228162514264337593543950335>", + }, + { + "name": "limb3", + "type": "core::internal::BoundedInt::<0, 79228162514264337593543950335>", + }, + ], + } + ] + + parser = AbiParser(abi_list) + parsed_abi = parser.parse() + + assert isinstance(parsed_abi, Abi) + + uint = cast( + UintType, parsed_abi.defined_structures["core::circuit::u384"].types["limb0"] + ) + assert uint.bits == 96 diff --git a/starknet_py/abi/v2/parser_transformer.py b/starknet_py/abi/v2/parser_transformer.py index 8207432fd..e5853eac7 100644 --- a/starknet_py/abi/v2/parser_transformer.py +++ b/starknet_py/abi/v2/parser_transformer.py @@ -1,3 +1,4 @@ +from math import log2 from typing import Any, List, Optional import lark @@ -25,6 +26,7 @@ | type_felt | type_bytes | type_uint + | type_bounded_int | type_contract_address | type_class_hash | type_storage_address @@ -40,6 +42,7 @@ type_bytes: "core::bytes_31::bytes31" type_bool: "core::bool" type_uint: "core::integer::u" INT + type_bounded_int: "core::internal::BoundedInt::<" INT "," WS? INT ">" type_contract_address: "core::starknet::contract_address::ContractAddress" type_class_hash: "core::starknet::class_hash::ClassHash" type_storage_address: "core::starknet::storage_access::StorageAddress" @@ -109,6 +112,17 @@ def type_uint(self, value: List[Token]) -> UintType: """ return UintType(int(value[0])) + def type_bounded_int(self, value: List[Token]) -> UintType: + """ + BoundedInt Uint type contains information about its ranges. They are present in the value[0] and value[2]. + """ + if value[0] != "0": + raise ValueError("BoundedInt should start from 0.") + + bits = log2(int(value[2]) + 1) + + return UintType(int(bits)) + def type_unit(self, _value: List[Any]) -> UnitType: """ `()` type. diff --git a/starknet_py/net/schemas/common.py b/starknet_py/net/schemas/common.py index acb0409df..d0e03d85c 100644 --- a/starknet_py/net/schemas/common.py +++ b/starknet_py/net/schemas/common.py @@ -89,6 +89,15 @@ class Felt(NumberAsHex): REGEX_PATTERN = r"^0x(0|[a-fA-F1-9]{1}[a-fA-F0-9]{0,62})$" +class EthAddress(NumberAsHex): + """ + Field used to serialize and deserialize ETH address type. + """ + + MAX_VALUE = 2**160 + REGEX_PATTERN = r"^0x[a-fA-F0-9]{40}$" + + class Uint64(NumberAsHex): """ Field used to serialize and deserialize RPC u64 type. diff --git a/starknet_py/net/schemas/rpc/transactions.py b/starknet_py/net/schemas/rpc/transactions.py index d08e192a5..f96cc82d2 100644 --- a/starknet_py/net/schemas/rpc/transactions.py +++ b/starknet_py/net/schemas/rpc/transactions.py @@ -27,6 +27,7 @@ ) from starknet_py.net.schemas.common import ( DAModeField, + EthAddress, ExecutionStatusField, Felt, FinalityStatusField, @@ -45,7 +46,7 @@ class L2toL1MessageSchema(Schema): l2_address = Felt(data_key="from_address", required=True) - l1_address = Felt(data_key="to_address", required=True) + l1_address = EthAddress(data_key="to_address", required=True) payload = fields.List(Felt(), data_key="payload", required=True) @post_load