diff --git a/Makefile b/Makefile index 0cce68d3b..f29626580 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,11 @@ endif .PHONY: build test coverage clean -# 154615699 corresponds to release v0.1.7 of Kakarot SSJ. -KKRT_SSJ_RELEASE_ID = 154615699 +# 176384150 corresponds to release v0.1.13 of Kakarot SSJ. +KKRT_SSJ_RELEASE_ID = 176384150 # Kakarot SSJ artifacts for precompiles. KKRT_SSJ_BUILD_ARTIFACT_URL = $(shell curl -L https://api.github.com/repos/kkrt-labs/kakarot-ssj/releases/${KKRT_SSJ_RELEASE_ID} | jq -r '.assets[0].browser_download_url') -KATANA_VERSION = v1.0.0-alpha.11 +KATANA_VERSION = v1.0.0-alpha.12 ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) BUILD_DIR = build @@ -35,7 +35,7 @@ $(SSJ_ZIP): fetch-ef-tests: poetry run python ./kakarot_scripts/ef_tests/fetch.py -setup: fetch-ssj-artifacts +setup: poetry install test: deploy diff --git a/kakarot_scripts/utils/starknet.py b/kakarot_scripts/utils/starknet.py index e1a81898b..aef217e78 100644 --- a/kakarot_scripts/utils/starknet.py +++ b/kakarot_scripts/utils/starknet.py @@ -243,6 +243,12 @@ def get_deployments(): @cache def get_artifact(contract_name): + # Cairo 0 artifacts + artifacts = list(BUILD_DIR.glob(f"*{contract_name}*.json")) + if artifacts: + return Artifact(sierra=None, casm=artifacts[0]) + + # Cairo 1 artifacts artifacts = list(CAIRO_DIR.glob(f"**/*{contract_name}.*.json")) or list( BUILD_DIR_SSJ.glob(f"**/*{contract_name}.*.json") ) @@ -255,10 +261,7 @@ def get_artifact(contract_name): ) return Artifact(sierra=sierra, casm=casm) - artifacts = list(BUILD_DIR.glob(f"**/*{contract_name}*.json")) - if not artifacts: - raise FileNotFoundError(f"No artifact found for {contract_name}") - return Artifact(sierra=None, casm=artifacts[0]) + raise FileNotFoundError(f"No artifact found for {contract_name}") @cache diff --git a/poetry.lock b/poetry.lock index 60116a536..88ea80843 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4687,4 +4687,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "9683cf7dacce11dd7a98325daaa9f1b56f136db87b14157f53cfafd3214ddcb6" +content-hash = "271fd12f0f0bc0cc2ce2ce46de531c36d22e5a0304c4569dc4015ce78e35e738" diff --git a/pyproject.toml b/pyproject.toml index c83b8e134..c3f4c768f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,6 @@ packages = [{ include = "kakarot_scripts" }, { include = "tests" }] [tool.poetry.dependencies] python = ">=3.10,<3.11" -starknet-py = "^0.23.0" cairo-lang = "0.13.1" python-dotenv = "^0.21.0" async-lru = "^2.0.4" @@ -16,6 +15,7 @@ toml = "^0.10.2" scikit-learn = "^1.5.1" seaborn = "^0.13.2" boto3 = "^1.35.12" +starknet-py = "0.23.0" [tool.poetry.group.dev.dependencies] pytest = "^8.1.1" diff --git a/solidity_contracts/src/EvmPrecompiles/EvmPrecompiles.sol b/solidity_contracts/src/EvmPrecompiles/EvmPrecompiles.sol new file mode 100644 index 000000000..1bd48ffa8 --- /dev/null +++ b/solidity_contracts/src/EvmPrecompiles/EvmPrecompiles.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +/// @title EVM Precompiles Integration +/// @notice Contract for integration testing of EVM precompiles. +/// @dev Implements functions for ECADD and ECMUL precompiles. +contract EvmPrecompiles { + /// @dev Address of the ECADD precompile + address private constant ECADD_PRECOMPILE = address(0x06); + /// @dev Address of the ECMUL precompile + address private constant ECMUL_PRECOMPILE = address(0x07); + + /// @dev Gas cost for ECADD call is 150 + uint256 private constant ECADD_GAS = 150; + /// @dev Gas cost for ECMUL call is 6000 + uint256 private constant ECMUL_GAS = 6000; + + /*////////////////////////////////////////////////////////////// + FUNCTIONS FOR PRECOMPILES + //////////////////////////////////////////////////////////////*/ + /// @notice Performs elliptic curve addition + /// @param x1 X coordinate of the first point + /// @param y1 Y coordinate of the first point + /// @param x2 X coordinate of the second point + /// @param y2 Y coordinate of the second point + /// @return success True if the operation was successful, false otherwise + /// @return x X coordinate of the result point + /// @return y Y coordinate of the result point + function ecAdd(uint256 x1, uint256 y1, uint256 x2, uint256 y2) external view returns (bool, uint256 x, uint256 y) { + bytes memory input = abi.encodePacked(x1, y1, x2, y2); + (bool success, bytes memory result) = ECADD_PRECOMPILE.staticcall{gas: ECADD_GAS}(input); + if (!success) { + return (false, 0, 0); + } + (x, y) = abi.decode(result, (uint256, uint256)); + return (true, x, y); + } + + /// @notice Performs elliptic curve scalar multiplication + /// @param x1 X coordinate of the point + /// @param y1 Y coordinate of the point + /// @param s Scalar for multiplication + /// @return success True if the operation was successful, false otherwise + /// @return x X coordinate of the result point + /// @return y Y coordinate of the result point + function ecMul(uint256 x1, uint256 y1, uint256 s) external view returns (bool, uint256 x, uint256 y) { + bytes memory input = abi.encodePacked(x1, y1, s); + (bool success, bytes memory result) = ECMUL_PRECOMPILE.staticcall{gas: ECMUL_GAS}(input); + if (!success) { + return (false, 0, 0); + } + (x, y) = abi.decode(result, (uint256, uint256)); + return (true, x, y); + } +} diff --git a/src/kakarot/interpreter.cairo b/src/kakarot/interpreter.cairo index c15d7e918..0c90821f3 100644 --- a/src/kakarot/interpreter.cairo +++ b/src/kakarot/interpreter.cairo @@ -76,19 +76,30 @@ namespace Interpreter { tempvar caller_code_address = parent_context.evm.message.code_address.evm; } tempvar caller_address = evm.message.caller; - let ( - output_len, output, gas_used, precompile_reverted - ) = Precompiles.exec_precompile( + let (output_len, output, gas_used, revert_code) = Precompiles.exec_precompile( evm.message.code_address.evm, evm.message.calldata_len, evm.message.calldata, caller_code_address, caller_address, ); - let evm = EVM.charge_gas(evm, gas_used); - let evm_reverted = is_not_zero(evm.reverted); - let success = (1 - precompile_reverted) * (1 - evm_reverted); - let evm = EVM.stop(evm, output_len, output, 1 - success); + + let precompile_reverted = is_not_zero(revert_code); + if (precompile_reverted != FALSE) { + // No need to charge gas as precompiles can only trigger EXCEPTIONAL_REVERT + // which will consume the entire gas of the context. + let evm = EVM.stop(evm, output_len, output, revert_code); + tempvar range_check_ptr = range_check_ptr; + tempvar evm = evm; + } else { + // Charge gas before stopping + let evm = EVM.charge_gas(evm, gas_used); + let evm = EVM.stop(evm, output_len, output, evm.reverted); + tempvar range_check_ptr = range_check_ptr; + tempvar evm = evm; + } + let range_check_ptr = [ap - 2]; + let evm = cast([ap - 1], model.EVM*); let is_cairo_precompile_called = PrecompilesHelpers.is_kakarot_precompile( evm.message.code_address.evm ); diff --git a/src/kakarot/precompiles/ecadd.cairo b/src/kakarot/precompiles/ecadd.cairo deleted file mode 100644 index 72162097b..000000000 --- a/src/kakarot/precompiles/ecadd.cairo +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Starkware dependencies -from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin -from starkware.cairo.common.cairo_secp.bigint import BigInt3 -from starkware.cairo.common.uint256 import Uint256 -from starkware.cairo.common.memcpy import memcpy - -// Internal dependencies -from utils.alt_bn128.alt_bn128_g1 import G1Point, ALT_BN128 -from utils.utils import Helpers - -// @title EcAdd Precompile related functions. -// @notice This file contains the logic required to run the ec_add precompile -// using alt_bn128 library -// @author @pedrobergamini -// @custom:namespace PrecompileEcAdd -namespace PrecompileEcAdd { - const PRECOMPILE_ADDRESS = 0x06; - const GAS_COST_EC_ADD = 150; - const G1POINT_BYTES_LEN = 32; - - // @notice Run the precompile. - // @param input_len The length of input array. - // @param input The input array. - // @return output_len The output length. - // @return output The output array. - // @return gas_used The gas usage of precompile. - func run{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr, - bitwise_ptr: BitwiseBuiltin*, - }(_address: felt, input_len: felt, input: felt*) -> ( - output_len: felt, output: felt*, gas_used: felt, reverted: felt - ) { - alloc_locals; - - let x0: BigInt3 = Helpers.bytes32_to_bigint(input); - let y0: BigInt3 = Helpers.bytes32_to_bigint(input + G1POINT_BYTES_LEN); - let x1: BigInt3 = Helpers.bytes32_to_bigint(input + G1POINT_BYTES_LEN * 2); - let y1: BigInt3 = Helpers.bytes32_to_bigint(input + G1POINT_BYTES_LEN * 3); - - with_attr error_message("Kakarot: ec_add failed") { - let point0: G1Point = G1Point(x0, y0); - let point1: G1Point = G1Point(x1, y1); - let result: G1Point = ALT_BN128.ec_add(point0, point1); - } - - let (bytes_x_len, output: felt*) = Helpers.bigint_to_bytes_array(result.x); - let (bytes_y_len, bytes_y: felt*) = Helpers.bigint_to_bytes_array(result.y); - memcpy(output + bytes_x_len, bytes_y, bytes_y_len); - - return (G1POINT_BYTES_LEN * 2, output, GAS_COST_EC_ADD, 0); - } -} diff --git a/src/kakarot/precompiles/ecmul.cairo b/src/kakarot/precompiles/ecmul.cairo deleted file mode 100644 index 102781fe8..000000000 --- a/src/kakarot/precompiles/ecmul.cairo +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Starkware dependencies -from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin -from starkware.cairo.common.cairo_secp.bigint import BigInt3 -from starkware.cairo.common.uint256 import Uint256 -from starkware.cairo.common.memcpy import memcpy - -// Internal dependencies -from utils.alt_bn128.alt_bn128_g1 import G1Point, ALT_BN128 -from utils.utils import Helpers - -// @title EcMul Precompile related functions. -// @notice This file contains the logic required to run the ec_mul precompile -// using alt_bn128 library -// @author @pedrobergamini -// @custom:namespace PrecompileEcMul -namespace PrecompileEcMul { - const PRECOMPILE_ADDRESS = 0x07; - const GAS_COST_EC_MUL = 6000; - const G1POINT_BYTES_LEN = 32; - - // @notice Run the precompile. - // @param input_len The length of input array. - // @param input The input array. - // @return output_len The output length. - // @return output The output array. - // @return gas_used The gas usage of precompile. - func run{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr, - bitwise_ptr: BitwiseBuiltin*, - }(_address: felt, input_len: felt, input: felt*) -> ( - output_len: felt, output: felt*, gas_used: felt, reverted: felt - ) { - alloc_locals; - - let x: BigInt3 = Helpers.bytes32_to_bigint(input); - let y: BigInt3 = Helpers.bytes32_to_bigint(input + G1POINT_BYTES_LEN); - let scalar: BigInt3 = Helpers.bytes32_to_bigint(input + G1POINT_BYTES_LEN * 2); - - with_attr error_message("Kakarot: ec_mul failed") { - let result: G1Point = ALT_BN128.ec_mul(G1Point(x, y), scalar); - } - - let (bytes_x_len, output: felt*) = Helpers.bigint_to_bytes_array(result.x); - let (bytes_y_len, bytes_y: felt*) = Helpers.bigint_to_bytes_array(result.y); - memcpy(output + bytes_x_len, bytes_y, bytes_y_len); - - return (G1POINT_BYTES_LEN * 2, output, GAS_COST_EC_MUL, 0); - } -} diff --git a/src/kakarot/precompiles/datacopy.cairo b/src/kakarot/precompiles/identity.cairo similarity index 83% rename from src/kakarot/precompiles/datacopy.cairo rename to src/kakarot/precompiles/identity.cairo index e3c2d8d86..a852e2e3f 100644 --- a/src/kakarot/precompiles/datacopy.cairo +++ b/src/kakarot/precompiles/identity.cairo @@ -11,13 +11,14 @@ from utils.utils import Helpers from kakarot.memory import Memory from kakarot.evm import EVM -// @title DataCopy precompile +// @title Identity precompile // @custom:precompile // @custom:address 0x04 // @notice This precompile serves as a cheaper way to copy data in memory -namespace PrecompileDataCopy { +namespace PrecompileIdentity { const PRECOMPILE_ADDRESS = 0x04; - const GAS_COST_DATACOPY = 15; + const GAS_IDENTITY = 15; + const GAS_IDENTITY_WORD = 3; // @notice Run the precompile. // @param input_len The length of input array. @@ -34,6 +35,6 @@ namespace PrecompileDataCopy { output_len: felt, output: felt*, gas_used: felt, reverted: felt ) { let (minimum_word_size) = Helpers.minimum_word_count(input_len); - return (input_len, input, 3 * minimum_word_size + GAS_COST_DATACOPY, 0); + return (input_len, input, GAS_IDENTITY_WORD * minimum_word_size + GAS_IDENTITY, 0); } } diff --git a/src/kakarot/precompiles/precompiles.cairo b/src/kakarot/precompiles/precompiles.cairo index 7c9652517..aea8dac01 100644 --- a/src/kakarot/precompiles/precompiles.cairo +++ b/src/kakarot/precompiles/precompiles.cairo @@ -12,7 +12,7 @@ from kakarot.storages import Kakarot_cairo1_helpers_class_hash from kakarot.errors import Errors from kakarot.precompiles.blake2f import PrecompileBlake2f from kakarot.precompiles.kakarot_precompiles import KakarotPrecompiles -from kakarot.precompiles.datacopy import PrecompileDataCopy +from kakarot.precompiles.identity import PrecompileIdentity from kakarot.precompiles.ec_recover import PrecompileEcRecover from kakarot.precompiles.p256verify import PrecompileP256Verify from kakarot.precompiles.ripemd160 import PrecompileRIPEMD160 @@ -37,7 +37,7 @@ namespace Precompiles { // @return output_len The output length. // @return output The output array. // @return gas_used The gas usage of precompile. - // @return reverted Whether the precompile ran successfully or not + // @return reverted The reverted code in {0(success), REVERTED, EXCEPTIONAL_HALT}. func exec_precompile{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -112,13 +112,13 @@ namespace Precompiles { ret; call PrecompileRIPEMD160.run; // 0x3 ret; - call PrecompileDataCopy.run; // 0x4 + call PrecompileIdentity.run; // 0x4 ret; call not_implemented_precompile; // 0x5 ret; - call not_implemented_precompile; // 0x6 + call external_precompile; // 0x6 ret; - call not_implemented_precompile; // 0x7 + call external_precompile; // 0x7 ret; call not_implemented_precompile; // 0x8 ret; @@ -161,10 +161,11 @@ namespace Precompiles { } // @notice A placeholder for attempts to call a precompile without permissions - // @dev Halts execution. - // @param evm_address The evm_address. - // @param input_len The length of the input array. - // @param input The input array. + // @dev Halts execution with an unauthorized precompile error. + // @return output_len The length of the error message. + // @return output The error message. + // @return gas_used The gas used (always 0 for this function). + // @return reverted The reverted code (EXCEPTIONAL_HALT). func unauthorized_precompile{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -172,14 +173,18 @@ namespace Precompiles { bitwise_ptr: BitwiseBuiltin*, }() -> (output_len: felt, output: felt*, gas_used: felt, reverted: felt) { let (revert_reason_len, revert_reason) = Errors.unauthorizedPrecompile(); - return (revert_reason_len, revert_reason, 0, Errors.REVERT); + return (revert_reason_len, revert_reason, 0, Errors.EXCEPTIONAL_HALT); } - // @notice A placeholder for precompile that don't exist. - // @dev Halts execution. - // @param evm_address The evm_address. - // @param input_len The length of the input array. - // @param input The input array. + // @notice A placeholder for precompiles that don't exist. + // @dev Halts execution with an unknown precompile error. + // @param evm_address The address of the unknown precompile. + // @param input_len The length of the input array (unused). + // @param input The input array (unused). + // @return output_len The length of the error message. + // @return output The error message. + // @return gas_used The gas used (always 0 for this function). + // @return reverted The reverted code (EXCEPTIONAL_HALT). func unknown_precompile{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -192,11 +197,15 @@ namespace Precompiles { return (revert_reason_len, revert_reason, 0, Errors.EXCEPTIONAL_HALT); } - // @notice A placeholder for precompile that are not implemented yet. - // @dev Halts execution. - // @param evm_address The evm_address. - // @param input_len The length of the input array. - // @param input The input array. + // @notice A placeholder for precompiles that are not implemented yet. + // @dev Halts execution with a not implemented precompile error. + // @param evm_address The address of the not implemented precompile. + // @param input_len The length of the input array (unused). + // @param input The input array (unused). + // @return output_len The length of the error message. + // @return output The error message. + // @return gas_used The gas used (always 0 for this function). + // @return reverted The reverted code (EXCEPTIONAL_HALT). func not_implemented_precompile{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -209,6 +218,15 @@ namespace Precompiles { return (revert_reason_len, revert_reason, 0, Errors.EXCEPTIONAL_HALT); } + // @notice Executes an external precompile using a Cairo 1 helper contract. + // @dev Calls the library_call_exec_precompile function of the ICairo1Helpers interface. + // @param evm_address The address of the external precompile. + // @param input_len The length of the input array. + // @param input The input array. + // @return output_len The length of the output data. + // @return output The output data. + // @return gas_used The gas used by the precompile execution. + // @return reverted 0 if successful, EXCEPTIONAL_HALT if execution failed. func external_precompile{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -228,7 +246,10 @@ namespace Precompiles { ) = ICairo1Helpers.library_call_exec_precompile( class_hash=implementation, address=evm_address, data_len=input_len, data=input ); - - return (return_data_len, return_data, gas, 1 - success); + if (success != FALSE) { + return (return_data_len, return_data, gas, 0); + } + // Precompiles can only revert with exceptions. Thus if the execution failed, it's an error EXCEPTIONAL_HALT. + return (return_data_len, return_data, 0, Errors.EXCEPTIONAL_HALT); } } diff --git a/src/utils/alt_bn128/alt_bn128_def.cairo b/src/utils/alt_bn128/alt_bn128_def.cairo deleted file mode 100644 index a6b97e6a4..000000000 --- a/src/utils/alt_bn128/alt_bn128_def.cairo +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Library copied from https://github.com/tekkac/cairo-alt_bn128 - -// Basic definitions for the alt_bn128 elliptic curve. -// The curve is given by the equation -// y^2 = x^3 + 3 -// over the field Z/p for -// p = p(u) = 36u^4 + 36u^3 + 24u^2 + 6u + 1 -// const p = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 -const P0 = 0x31ca8d3c208c16d87cfd47; -const P1 = 0x16da060561765e05aa45a1; -const P2 = 0x30644e72e131a029b8504; - -// The following constants represent the size of the curve: -// n = n(u) = 36u^4 + 36u^3 + 18u^2 + 6u + 1 -// const n = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 -const N0 = 0x39709143e1f593f0000001; -const N1 = 0x16da06056174a0cfa121e6; -const N2 = 0x30644e72e131a029b8504; diff --git a/src/utils/alt_bn128/alt_bn128_field.cairo b/src/utils/alt_bn128/alt_bn128_field.cairo deleted file mode 100644 index a247912ee..000000000 --- a/src/utils/alt_bn128/alt_bn128_field.cairo +++ /dev/null @@ -1,556 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Library copied from https://github.com/tekkac/cairo-alt_bn128 - -// Starkware dependencies -from starkware.cairo.common.bitwise import bitwise_and -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin - -// Internal dependencies -from utils.alt_bn128.bigint import ( - BASE, - BigInt3, - UnreducedBigInt3, - UnreducedBigInt5, - nondet_bigint3, - bigint_mul, -) -from utils.alt_bn128.alt_bn128_def import P0, P1, P2 - -// FIELD STRUCTURES -struct FQ2 { - e0: BigInt3, - e1: BigInt3, -} - -struct FQ12 { - e0: BigInt3, - e1: BigInt3, - e2: BigInt3, - e3: BigInt3, - e4: BigInt3, - e5: BigInt3, - e6: BigInt3, - e7: BigInt3, - e8: BigInt3, - e9: BigInt3, - eA: BigInt3, - eB: BigInt3, -} - -struct unreducedFQ12 { - e0: UnreducedBigInt5, - e1: UnreducedBigInt5, - e2: UnreducedBigInt5, - e3: UnreducedBigInt5, - e4: UnreducedBigInt5, - e5: UnreducedBigInt5, - e6: UnreducedBigInt5, - e7: UnreducedBigInt5, - e8: UnreducedBigInt5, - e9: UnreducedBigInt5, - eA: UnreducedBigInt5, - eB: UnreducedBigInt5, -} - -// FIELD CONSTANTS -func fq_zero() -> (res: BigInt3) { - return (BigInt3(0, 0, 0),); -} - -func fq2_zero() -> (res: FQ2) { - return (FQ2(e0=BigInt3(0, 0, 0), e1=BigInt3(0, 0, 0)),); -} - -func fq12_zero() -> (res: FQ12) { - return ( - FQ12( - e0=BigInt3(0, 0, 0), - e1=BigInt3(0, 0, 0), - e2=BigInt3(0, 0, 0), - e3=BigInt3(0, 0, 0), - e4=BigInt3(0, 0, 0), - e5=BigInt3(0, 0, 0), - e6=BigInt3(0, 0, 0), - e7=BigInt3(0, 0, 0), - e8=BigInt3(0, 0, 0), - e9=BigInt3(0, 0, 0), - eA=BigInt3(0, 0, 0), - eB=BigInt3(0, 0, 0), - ), - ); -} - -func fq12_one() -> (res: FQ12) { - return ( - FQ12( - e0=BigInt3(1, 0, 0), - e1=BigInt3(0, 0, 0), - e2=BigInt3(0, 0, 0), - e3=BigInt3(0, 0, 0), - e4=BigInt3(0, 0, 0), - e5=BigInt3(0, 0, 0), - e6=BigInt3(0, 0, 0), - e7=BigInt3(0, 0, 0), - e8=BigInt3(0, 0, 0), - e9=BigInt3(0, 0, 0), - eA=BigInt3(0, 0, 0), - eB=BigInt3(0, 0, 0), - ), - ); -} - -func verify_zero3{range_check_ptr}(val: BigInt3) { - alloc_locals; - local flag; - local q; - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.cairo.common.math_utils import as_int - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - - v = pack(ids.val, PRIME) - q, r = divmod(v, P) - assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." - - ids.flag = 1 if q > 0 else 0 - q = q if q > 0 else 0-q - ids.q = q % PRIME - %} - assert [range_check_ptr] = q + 2 ** 127; - - tempvar carry1 = ((2 * flag - 1) * q * P0 - val.d0) / BASE; - assert [range_check_ptr + 1] = carry1 + 2 ** 127; - - tempvar carry2 = ((2 * flag - 1) * q * P1 - val.d1 + carry1) / BASE; - assert [range_check_ptr + 2] = carry2 + 2 ** 127; - - assert (2 * flag - 1) * q * P2 - val.d2 + carry2 = 0; - - let range_check_ptr = range_check_ptr + 3; - - return (); -} - -func verify_zero5{range_check_ptr}(val: UnreducedBigInt5) { - alloc_locals; - local flag; - local q1; - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.cairo.common.math_utils import as_int - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - - v3 = as_int(ids.val.d3, PRIME) - v4 = as_int(ids.val.d4, PRIME) - v = pack(ids.val, PRIME) + v3*2**258 + v4*2**344 - - q, r = divmod(v, P) - assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2, ids.val.d3, ids.val.d4}." - - # Since q usually doesn't fit BigInt3, divide it again - ids.flag = 1 if q > 0 else 0 - q = q if q > 0 else 0-q - q1, q2 = divmod(q, P) - ids.q1 = q1 - value = k = q2 - %} - let (k) = nondet_bigint3(); - let fullk = BigInt3(q1 * P0 + k.d0, q1 * P1 + k.d1, q1 * P2 + k.d2); - let P = BigInt3(P0, P1, P2); - let (k_n) = bigint_mul(fullk, P); - - // val mod n = 0, so val = k_n - tempvar carry1 = ((2 * flag - 1) * k_n.d0 - val.d0) / BASE; - assert [range_check_ptr + 0] = carry1 + 2 ** 127; - - tempvar carry2 = ((2 * flag - 1) * k_n.d1 - val.d1 + carry1) / BASE; - assert [range_check_ptr + 1] = carry2 + 2 ** 127; - - tempvar carry3 = ((2 * flag - 1) * k_n.d2 - val.d2 + carry2) / BASE; - assert [range_check_ptr + 2] = carry3 + 2 ** 127; - - tempvar carry4 = ((2 * flag - 1) * k_n.d3 - val.d3 + carry3) / BASE; - assert [range_check_ptr + 3] = carry4 + 2 ** 127; - - assert (2 * flag - 1) * k_n.d4 - val.d4 + carry4 = 0; - - let range_check_ptr = range_check_ptr + 4; - - return (); -} - -// returns 1 if x ==0 mod alt_bn128 prime -func is_zero{range_check_ptr}(x: BigInt3) -> (res: felt) { - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - x = pack(ids.x, PRIME) % P - %} - if (nondet %{ x == 0 %} != 0) { - verify_zero3(x); - // verify_zero5(UnreducedBigInt5(d0=x.d0, d1=x.d1, d2=x.d2, d3=0, d4=0)) - return (res=1); - } - - %{ - from starkware.python.math_utils import div_mod - value = x_inv = div_mod(1, x, P) - %} - let (x_inv) = nondet_bigint3(); - let (x_x_inv) = bigint_mul(x, x_inv); - - // Check that x * x_inv = 1 to verify that x != 0. - verify_zero5( - UnreducedBigInt5( - d0=x_x_inv.d0 - 1, d1=x_x_inv.d1, d2=x_x_inv.d2, d3=x_x_inv.d3, d4=x_x_inv.d4 - ), - ); - return (res=0); -} - -// FQ12 verify - -func verify_zero_fq12{range_check_ptr}(x: FQ12) { - verify_zero3(x.e0); - verify_zero3(x.e1); - verify_zero3(x.e2); - verify_zero3(x.e3); - verify_zero3(x.e4); - verify_zero3(x.e5); - verify_zero3(x.e6); - verify_zero3(x.e7); - verify_zero3(x.e8); - verify_zero3(x.e9); - verify_zero3(x.eA); - verify_zero3(x.eB); - return (); -} - -func fq_eq_zero(x: BigInt3) -> (res: felt) { - if (x.d0 != 0) { - return (res=0); - } - if (x.d1 != 0) { - return (res=0); - } - if (x.d2 != 0) { - return (res=0); - } - return (res=1); -} - -func fq12_eq_zero(x: FQ12) -> (res: felt) { - let (e0_is_zero) = fq_eq_zero(x.e0); - if (e0_is_zero == 0) { - return (res=0); - } - let (e1_is_zero) = fq_eq_zero(x.e1); - if (e1_is_zero == 0) { - return (res=0); - } - let (e2_is_zero) = fq_eq_zero(x.e2); - if (e2_is_zero == 0) { - return (res=0); - } - let (e3_is_zero) = fq_eq_zero(x.e3); - if (e3_is_zero == 0) { - return (res=0); - } - let (e4_is_zero) = fq_eq_zero(x.e4); - if (e4_is_zero == 0) { - return (res=0); - } - let (e5_is_zero) = fq_eq_zero(x.e5); - if (e5_is_zero == 0) { - return (res=0); - } - let (e6_is_zero) = fq_eq_zero(x.e6); - if (e6_is_zero == 0) { - return (res=0); - } - let (e7_is_zero) = fq_eq_zero(x.e7); - if (e7_is_zero == 0) { - return (res=0); - } - let (e8_is_zero) = fq_eq_zero(x.e8); - if (e8_is_zero == 0) { - return (res=0); - } - let (e9_is_zero) = fq_eq_zero(x.e9); - if (e9_is_zero == 0) { - return (res=0); - } - let (eA_is_zero) = fq_eq_zero(x.eA); - if (eA_is_zero == 0) { - return (res=0); - } - let (eB_is_zero) = fq_eq_zero(x.eB); - if (eB_is_zero == 0) { - return (res=0); - } - return (res=1); -} - -func fq12_is_zero{range_check_ptr}(x: FQ12) -> (res: felt) { - %{ - import sys, os - cwd = os.getcwd() - sys.path.append(cwd) - - from utils.bn128_field import FQ, FQ12 - from utils.bn128_utils import parse_fq12 - - val = list(map(FQ, parse_fq12(ids.x))) - - if FQ12(val) == FQ12([0]*12): - x = 0 - else: - x = 1 - %} - if (nondet %{ x == 0 %} != 0) { - verify_zero_fq12(x); - return (res=1); - } - - %{ - val = list(map(FQ, parse_fq12(ids.x))) - val = FQ12(val).inv() - value = list(map(lambda x: x.n, val.coeffs)) - %} - let (x_inv) = nondet_fq12(); - - // TODO VERIF x * x_inv - 1 = 0 - return (res=0); -} - -// Difference of two FQ12, resulting FQ12 BigInt3 limbs can be negative -func fq12_diff(x: FQ12, y: FQ12) -> (res: FQ12) { - return ( - res=FQ12( - BigInt3(d0=x.e0.d0 - y.e0.d0, d1=x.e0.d1 - y.e0.d1, d2=x.e0.d2 - y.e0.d2), - BigInt3(d0=x.e1.d0 - y.e1.d0, d1=x.e1.d1 - y.e1.d1, d2=x.e1.d2 - y.e1.d2), - BigInt3(d0=x.e2.d0 - y.e2.d0, d1=x.e2.d1 - y.e2.d1, d2=x.e2.d2 - y.e2.d2), - BigInt3(d0=x.e3.d0 - y.e3.d0, d1=x.e3.d1 - y.e3.d1, d2=x.e3.d2 - y.e3.d2), - BigInt3(d0=x.e4.d0 - y.e4.d0, d1=x.e4.d1 - y.e4.d1, d2=x.e4.d2 - y.e4.d2), - BigInt3(d0=x.e5.d0 - y.e5.d0, d1=x.e5.d1 - y.e5.d1, d2=x.e5.d2 - y.e5.d2), - BigInt3(d0=x.e6.d0 - y.e6.d0, d1=x.e6.d1 - y.e6.d1, d2=x.e6.d2 - y.e6.d2), - BigInt3(d0=x.e7.d0 - y.e7.d0, d1=x.e7.d1 - y.e7.d1, d2=x.e7.d2 - y.e7.d2), - BigInt3(d0=x.e8.d0 - y.e8.d0, d1=x.e8.d1 - y.e8.d1, d2=x.e8.d2 - y.e8.d2), - BigInt3(d0=x.e9.d0 - y.e9.d0, d1=x.e9.d1 - y.e9.d1, d2=x.e9.d2 - y.e9.d2), - BigInt3(d0=x.eA.d0 - y.eA.d0, d1=x.eA.d1 - y.eA.d1, d2=x.eA.d2 - y.eA.d2), - BigInt3(d0=x.eB.d0 - y.eB.d0, d1=x.eB.d1 - y.eB.d1, d2=x.eB.d2 - y.eB.d2), - ), - ); -} - -func fq12_sum(x: FQ12, y: FQ12) -> (res: FQ12) { - return ( - res=FQ12( - BigInt3(d0=x.e0.d0 + y.e0.d0, d1=x.e0.d1 + y.e0.d1, d2=x.e0.d2 + y.e0.d2), - BigInt3(d0=x.e1.d0 + y.e1.d0, d1=x.e1.d1 + y.e1.d1, d2=x.e1.d2 + y.e1.d2), - BigInt3(d0=x.e2.d0 + y.e2.d0, d1=x.e2.d1 + y.e2.d1, d2=x.e2.d2 + y.e2.d2), - BigInt3(d0=x.e3.d0 + y.e3.d0, d1=x.e3.d1 + y.e3.d1, d2=x.e3.d2 + y.e3.d2), - BigInt3(d0=x.e4.d0 + y.e4.d0, d1=x.e4.d1 + y.e4.d1, d2=x.e4.d2 + y.e4.d2), - BigInt3(d0=x.e5.d0 + y.e5.d0, d1=x.e5.d1 + y.e5.d1, d2=x.e5.d2 + y.e5.d2), - BigInt3(d0=x.e6.d0 + y.e6.d0, d1=x.e6.d1 + y.e6.d1, d2=x.e6.d2 + y.e6.d2), - BigInt3(d0=x.e7.d0 + y.e7.d0, d1=x.e7.d1 + y.e7.d1, d2=x.e7.d2 + y.e7.d2), - BigInt3(d0=x.e8.d0 + y.e8.d0, d1=x.e8.d1 + y.e8.d1, d2=x.e8.d2 + y.e8.d2), - BigInt3(d0=x.e9.d0 + y.e9.d0, d1=x.e9.d1 + y.e9.d1, d2=x.e9.d2 + y.e9.d2), - BigInt3(d0=x.eA.d0 + y.eA.d0, d1=x.eA.d1 + y.eA.d1, d2=x.eA.d2 + y.eA.d2), - BigInt3(d0=x.eB.d0 + y.eB.d0, d1=x.eB.d1 + y.eB.d1, d2=x.eB.d2 + y.eB.d2), - ), - ); -} - -// TODO - -// FIELD MULTIPLICATION - -// func ufq12_mul{range_check_ptr}(a : FQ12, b : FQ12) -> (res : unreducedFQ12): -// let ab_e0 = bigint_mul(a.e0, b.d0) -// let ab_e0 = bigint_mul(a.e0, b.d0) -// return ( -// unreducedFQ12( -// e0= - -// end - -// TODO deterministic (unreduced FQ12?) -func fq12_mul{range_check_ptr}(a: FQ12, b: FQ12) -> (res: FQ12) { - %{ - import sys, os - cwd = os.getcwd() - sys.path.append(cwd) - from utils.bn128_field import FQ, FQ12 - from utils.bn128_utils import parse_fq12, print_g12 - a = FQ12(list(map(FQ, parse_fq12(ids.a)))) - b = FQ12(list(map(FQ, parse_fq12(ids.b)))) - value = res = list(map(lambda x: x.n, (a*b).coeffs)) - # print("a*b =", value) - %} - let (res) = nondet_fq12(); - // TODO CHECKS - return (res=res); -} - -func fq12_pow_inner{range_check_ptr}(x: FQ12, n: felt, m: felt) -> (pow2: FQ12, res: FQ12) { - if (m == 0) { - assert n = 0; - let (one) = fq12_one(); - return (pow2=x, res=one); - } - - alloc_locals; - let (x_sqr) = fq12_mul(x, x); - - %{ memory[ap] = (ids.n % PRIME) % 2 %} - jmp odd if [ap] != 0, ap++; - return fq12_pow_inner(x=x_sqr, n=n / 2, m=m - 1); - - odd: - let (inner_pow, inner_res) = fq12_pow_inner(x=x_sqr, n=(n - 1) / 2, m=m - 1); - let (res) = fq12_mul(inner_res, x); - return (inner_pow, res); -} - -func fq12_pow_3{range_check_ptr}(x: FQ12, n: BigInt3) -> (pow2: FQ12, res: FQ12) { - alloc_locals; - let (pow2_0: FQ12, local res0: FQ12) = fq12_pow_inner(x, n.d0, 86); - let (pow2_1: FQ12, local res1: FQ12) = fq12_pow_inner(pow2_0, n.d1, 86); - let (pow2_2, local res2: FQ12) = fq12_pow_inner(pow2_1, n.d2, 86); - let (res: FQ12) = fq12_mul(res0, res1); - let (res: FQ12) = fq12_mul(res, res2); - return (pow2_2, res); -} - -func fq12_pow_12{range_check_ptr}(x: FQ12, n: FQ12) -> (res: FQ12) { - alloc_locals; - let (pow2_0: FQ12, local res0: FQ12) = fq12_pow_3(x, n.e0); - let (pow2_1: FQ12, local res1: FQ12) = fq12_pow_3(pow2_0, n.e1); - let (pow2_2: FQ12, local res2: FQ12) = fq12_pow_3(pow2_1, n.e2); - let (pow2_3: FQ12, local res3: FQ12) = fq12_pow_3(pow2_2, n.e3); - let (pow2_4: FQ12, local res4: FQ12) = fq12_pow_3(pow2_3, n.e4); - let (pow2_5: FQ12, local res5: FQ12) = fq12_pow_3(pow2_4, n.e5); - let (pow2_6: FQ12, local res6: FQ12) = fq12_pow_3(pow2_5, n.e6); - let (pow2_7: FQ12, local res7: FQ12) = fq12_pow_3(pow2_6, n.e7); - let (pow2_8: FQ12, local res8: FQ12) = fq12_pow_3(pow2_7, n.e8); - let (pow2_9: FQ12, local res9: FQ12) = fq12_pow_3(pow2_8, n.e9); - let (pow2_A: FQ12, local resA: FQ12) = fq12_pow_3(pow2_9, n.eA); - // Simplifications since eB = 0 - // let (pow2_B : FQ12, local resB : FQ12) = fq12_pow_3(pow2_A, n.eB) - let (local res01: FQ12) = fq12_mul(res0, res1); - let (local res23: FQ12) = fq12_mul(res2, res3); - let (local res45: FQ12) = fq12_mul(res4, res5); - let (local res67: FQ12) = fq12_mul(res6, res7); - let (local res89: FQ12) = fq12_mul(res8, res9); - // let (local resAB : FQ12) = fq12_mul(resA, resB) - let (local res0123: FQ12) = fq12_mul(res01, res23); - let (local res4567: FQ12) = fq12_mul(res45, res67); - // let (local res89AB : FQ12) = fq12_mul(res89, resAB) - let (local res89A: FQ12) = fq12_mul(res89, resA); - let (local res0123: FQ12) = fq12_mul(res01, res23); - let (local res0__7: FQ12) = fq12_mul(res0123, res4567); - let (res: FQ12) = fq12_mul(res0__7, res89A); - return (res,); -} - -// Hint argument: value -// a 12 element list of field elements -func nondet_fq12{range_check_ptr}() -> (res: FQ12) { - let res: FQ12 = [cast(ap + 38, FQ12*)]; - %{ - from starkware.cairo.common.cairo_secp.secp_utils import split - - r = ids.res - var_list = [r.e0, r.e1, r.e2, r.e3, r.e4, r.e5, - r.e6, r.e7, r.e8, r.e9, r.eA, r.eB] - #segments.write_arg(ids.res.e0.address_, split(val[0])) - for (var, val) in zip(var_list, value): - segments.write_arg(var.address_, split(val)) - %} - const MAX_SUM = 12 * 3 * (2 ** 86 - 1); - // TODO RANGE CHECKS? (WHY THE ASSERT LIKE THIS BTW?) - assert [range_check_ptr] = MAX_SUM - ( - res.e0.d0 + - res.e0.d1 + - res.e0.d2 + - res.e1.d0 + - res.e1.d1 + - res.e1.d2 + - res.e2.d0 + - res.e2.d1 + - res.e2.d2 + - res.e3.d0 + - res.e3.d1 + - res.e3.d2 + - res.e4.d0 + - res.e4.d1 + - res.e4.d2 + - res.e5.d0 + - res.e5.d1 + - res.e5.d2 + - res.e6.d0 + - res.e6.d1 + - res.e6.d2 + - res.e7.d0 + - res.e7.d1 + - res.e7.d2 + - res.e8.d0 + - res.e8.d1 + - res.e8.d2 + - res.e9.d0 + - res.e9.d1 + - res.e9.d2 + - res.eA.d0 + - res.eA.d1 + - res.eA.d2 + - res.eB.d0 + - res.eB.d1 + - res.eB.d2 - ); - - tempvar range_check_ptr = range_check_ptr + 37; - [range_check_ptr - 1] = res.e0.d0, ap++; - [range_check_ptr - 2] = res.e0.d1, ap++; - [range_check_ptr - 3] = res.e0.d2, ap++; - [range_check_ptr - 4] = res.e1.d0, ap++; - [range_check_ptr - 5] = res.e1.d1, ap++; - [range_check_ptr - 6] = res.e1.d2, ap++; - [range_check_ptr - 7] = res.e2.d0, ap++; - [range_check_ptr - 8] = res.e2.d1, ap++; - [range_check_ptr - 9] = res.e2.d2, ap++; - [range_check_ptr - 10] = res.e3.d0, ap++; - [range_check_ptr - 11] = res.e3.d1, ap++; - [range_check_ptr - 12] = res.e3.d2, ap++; - [range_check_ptr - 13] = res.e4.d0, ap++; - [range_check_ptr - 14] = res.e4.d1, ap++; - [range_check_ptr - 15] = res.e4.d2, ap++; - [range_check_ptr - 16] = res.e5.d0, ap++; - [range_check_ptr - 17] = res.e5.d1, ap++; - [range_check_ptr - 18] = res.e5.d2, ap++; - [range_check_ptr - 19] = res.e6.d0, ap++; - [range_check_ptr - 20] = res.e6.d1, ap++; - [range_check_ptr - 21] = res.e6.d2, ap++; - [range_check_ptr - 22] = res.e7.d0, ap++; - [range_check_ptr - 23] = res.e7.d1, ap++; - [range_check_ptr - 24] = res.e7.d2, ap++; - [range_check_ptr - 25] = res.e8.d0, ap++; - [range_check_ptr - 26] = res.e8.d1, ap++; - [range_check_ptr - 27] = res.e8.d2, ap++; - [range_check_ptr - 28] = res.e9.d0, ap++; - [range_check_ptr - 29] = res.e9.d1, ap++; - [range_check_ptr - 30] = res.e9.d2, ap++; - [range_check_ptr - 31] = res.eA.d0, ap++; - [range_check_ptr - 32] = res.eA.d1, ap++; - [range_check_ptr - 33] = res.eA.d2, ap++; - [range_check_ptr - 34] = res.eB.d0, ap++; - [range_check_ptr - 35] = res.eB.d1, ap++; - [range_check_ptr - 36] = res.eB.d2, ap++; - static_assert &res + FQ12.SIZE == ap; - return (res=res); -} diff --git a/src/utils/alt_bn128/alt_bn128_g1.cairo b/src/utils/alt_bn128/alt_bn128_g1.cairo deleted file mode 100644 index fc1ee60db..000000000 --- a/src/utils/alt_bn128/alt_bn128_g1.cairo +++ /dev/null @@ -1,338 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Library copied from https://github.com/tekkac/cairo-alt_bn128 - -// Starkware dependencies -from starkware.cairo.common.cairo_secp.bigint import UnreducedBigInt3, BigInt3 - -// Internal dependencies -from utils.alt_bn128.bigint import nondet_bigint3, UnreducedBigInt5, bigint_mul -from utils.alt_bn128.alt_bn128_field import is_zero, verify_zero5 -from utils.alt_bn128.alt_bn128_def import P0, P1, P2 - -// Represents a point on the elliptic curve. -// The zero point is represented using pt.x=0, as there is no point on the curve with this x value. -struct G1Point { - x: BigInt3, - y: BigInt3, -} - -namespace ALT_BN128 { - // Returns the slope of the elliptic curve at the given point. - // The slope is used to compute pt + pt. - // Assumption: pt != 0. - func compute_doubling_slope{range_check_ptr}(pt: G1Point) -> (slope: BigInt3) { - // Note that y cannot be zero: assume that it is, then pt = -pt, so 2 * pt = 0, which - // contradicts the fact that the size of the curve is odd. - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.python.math_utils import div_mod - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - - # Compute the slope. - x = pack(ids.pt.x, PRIME) - y = pack(ids.pt.y, PRIME) - value = slope = div_mod(3 * x ** 2, 2 * y, P) - %} - let (slope: BigInt3) = nondet_bigint3(); - - let (x_sqr: UnreducedBigInt5) = bigint_mul(pt.x, pt.x); - let (slope_y: UnreducedBigInt5) = bigint_mul(slope, pt.y); - - verify_zero5( - UnreducedBigInt5( - d0=3 * x_sqr.d0 - 2 * slope_y.d0, - d1=3 * x_sqr.d1 - 2 * slope_y.d1, - d2=3 * x_sqr.d2 - 2 * slope_y.d2, - d3=3 * x_sqr.d3 - 2 * slope_y.d3, - d4=3 * x_sqr.d4 - 2 * slope_y.d4, - ), - ); - - return (slope=slope); - } - - // Returns the slope of the line connecting the two given points. - // The slope is used to compute pt0 + pt1. - // Assumption: pt0.x != pt1.x (mod field prime). - func compute_slope{range_check_ptr}(pt0: G1Point, pt1: G1Point) -> (slope: BigInt3) { - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.python.math_utils import div_mod - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - # Compute the slope. - x0 = pack(ids.pt0.x, PRIME) - y0 = pack(ids.pt0.y, PRIME) - x1 = pack(ids.pt1.x, PRIME) - y1 = pack(ids.pt1.y, PRIME) - value = slope = div_mod(y0 - y1, x0 - x1, P) - %} - let (slope) = nondet_bigint3(); - - let x_diff = BigInt3( - d0=pt0.x.d0 - pt1.x.d0, d1=pt0.x.d1 - pt1.x.d1, d2=pt0.x.d2 - pt1.x.d2 - ); - let (x_diff_slope: UnreducedBigInt5) = bigint_mul(x_diff, slope); - - verify_zero5( - UnreducedBigInt5( - d0=x_diff_slope.d0 - pt0.y.d0 + pt1.y.d0, - d1=x_diff_slope.d1 - pt0.y.d1 + pt1.y.d1, - d2=x_diff_slope.d2 - pt0.y.d2 + pt1.y.d2, - d3=x_diff_slope.d3, - d4=x_diff_slope.d4, - ), - ); - - return (slope,); - } - - // Given a point 'pt' on the elliptic curve, computes pt + pt. - func ec_double{range_check_ptr}(pt: G1Point) -> (res: G1Point) { - if (pt.x.d0 == 0) { - if (pt.x.d1 == 0) { - if (pt.x.d2 == 0) { - return (pt,); - } - } - } - - let (slope: BigInt3) = compute_doubling_slope(pt); - let (slope_sqr: UnreducedBigInt5) = bigint_mul(slope, slope); - - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - slope = pack(ids.slope, PRIME) - x = pack(ids.pt.x, PRIME) - y = pack(ids.pt.y, PRIME) - - value = new_x = (pow(slope, 2, P) - 2 * x) % P - %} - let (new_x: BigInt3) = nondet_bigint3(); - - %{ value = new_y = (slope * (x - new_x) - y) % P %} - let (new_y: BigInt3) = nondet_bigint3(); - - verify_zero5( - UnreducedBigInt5( - d0=slope_sqr.d0 - new_x.d0 - 2 * pt.x.d0, - d1=slope_sqr.d1 - new_x.d1 - 2 * pt.x.d1, - d2=slope_sqr.d2 - new_x.d2 - 2 * pt.x.d2, - d3=slope_sqr.d3, - d4=slope_sqr.d4, - ), - ); - - let (x_diff_slope: UnreducedBigInt5) = bigint_mul( - BigInt3(d0=pt.x.d0 - new_x.d0, d1=pt.x.d1 - new_x.d1, d2=pt.x.d2 - new_x.d2), slope - ); - - verify_zero5( - UnreducedBigInt5( - d0=x_diff_slope.d0 - pt.y.d0 - new_y.d0, - d1=x_diff_slope.d1 - pt.y.d1 - new_y.d1, - d2=x_diff_slope.d2 - pt.y.d2 - new_y.d2, - d3=x_diff_slope.d3, - d4=x_diff_slope.d4, - ), - ); - - return (G1Point(new_x, new_y),); - } - - // Adds two points on the elliptic curve. - // Assumption: pt0.x != pt1.x (however, pt0 = pt1 = 0 is allowed). - // Note that this means that the function cannot be used if pt0 = pt1 - // (use ec_double() in this case) or pt0 = -pt1 (the result is 0 in this case). - func fast_ec_add{range_check_ptr}(pt0: G1Point, pt1: G1Point) -> (res: G1Point) { - if (pt0.x.d0 == 0) { - if (pt0.x.d1 == 0) { - if (pt0.x.d2 == 0) { - return (pt1,); - } - } - } - if (pt1.x.d0 == 0) { - if (pt1.x.d1 == 0) { - if (pt1.x.d2 == 0) { - return (pt0,); - } - } - } - - let (slope: BigInt3) = compute_slope(pt0, pt1); - let (slope_sqr: UnreducedBigInt5) = bigint_mul(slope, slope); - - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - - P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - slope = pack(ids.slope, PRIME) - x0 = pack(ids.pt0.x, PRIME) - x1 = pack(ids.pt1.x, PRIME) - y0 = pack(ids.pt0.y, PRIME) - - value = new_x = (pow(slope, 2, P) - x0 - x1) % P - %} - let (new_x: BigInt3) = nondet_bigint3(); - - %{ value = new_y = (slope * (x0 - new_x) - y0) % P %} - let (new_y: BigInt3) = nondet_bigint3(); - - verify_zero5( - UnreducedBigInt5( - d0=slope_sqr.d0 - new_x.d0 - pt0.x.d0 - pt1.x.d0, - d1=slope_sqr.d1 - new_x.d1 - pt0.x.d1 - pt1.x.d1, - d2=slope_sqr.d2 - new_x.d2 - pt0.x.d2 - pt1.x.d2, - d3=slope_sqr.d3, - d4=slope_sqr.d4, - ), - ); - - let (x_diff_slope: UnreducedBigInt5) = bigint_mul( - BigInt3(d0=pt0.x.d0 - new_x.d0, d1=pt0.x.d1 - new_x.d1, d2=pt0.x.d2 - new_x.d2), slope - ); - - verify_zero5( - UnreducedBigInt5( - d0=x_diff_slope.d0 - pt0.y.d0 - new_y.d0, - d1=x_diff_slope.d1 - pt0.y.d1 - new_y.d1, - d2=x_diff_slope.d2 - pt0.y.d2 - new_y.d2, - d3=x_diff_slope.d3, - d4=x_diff_slope.d4, - ), - ); - - return (G1Point(new_x, new_y),); - } - - // Same as fast_ec_add, except that the cases pt0 = ±pt1 are supported. - func ec_add{range_check_ptr}(pt0: G1Point, pt1: G1Point) -> (res: G1Point) { - let x_diff = BigInt3( - d0=pt0.x.d0 - pt1.x.d0, d1=pt0.x.d1 - pt1.x.d1, d2=pt0.x.d2 - pt1.x.d2 - ); - let (same_x: felt) = is_zero(x_diff); - if (same_x == 0) { - // pt0.x != pt1.x so we can use fast_ec_add. - return fast_ec_add(pt0, pt1); - } - - // We have pt0.x = pt1.x. This implies pt0.y = ±pt1.y. - // Check whether pt0.y = -pt1.y. - let y_sum = BigInt3(d0=pt0.y.d0 + pt1.y.d0, d1=pt0.y.d1 + pt1.y.d1, d2=pt0.y.d2 + pt1.y.d2); - let (opposite_y: felt) = is_zero(y_sum); - if (opposite_y != 0) { - // pt0.y = -pt1.y. - // Note that the case pt0 = pt1 = 0 falls into this branch as well. - let ZERO_POINT = G1Point(BigInt3(0, 0, 0), BigInt3(0, 0, 0)); - return (ZERO_POINT,); - } else { - // pt0.y = pt1.y. - return ec_double(pt0); - } - } - - // Given 0 <= m < 250, a scalar and a point on the elliptic curve, pt, - // verifies that 0 <= scalar < 2**m and returns (2**m * pt, scalar * pt). - func ec_mul_inner{range_check_ptr}(pt: G1Point, scalar: felt, m: felt) -> ( - pow2: G1Point, res: G1Point - ) { - if (m == 0) { - assert scalar = 0; - let ZERO_POINT = G1Point(BigInt3(0, 0, 0), BigInt3(0, 0, 0)); - return (pow2=pt, res=ZERO_POINT); - } - - alloc_locals; - let (double_pt: G1Point) = ec_double(pt); - %{ memory[ap] = (ids.scalar % PRIME) % 2 %} - jmp odd if [ap] != 0, ap++; - return ec_mul_inner(pt=double_pt, scalar=scalar / 2, m=m - 1); - - odd: - let (local inner_pow2: G1Point, inner_res: G1Point) = ec_mul_inner( - pt=double_pt, scalar=(scalar - 1) / 2, m=m - 1 - ); - // Here inner_res = (scalar - 1) / 2 * double_pt = (scalar - 1) * pt. - // Assume pt != 0 and that inner_res = ±pt. We obtain (scalar - 1) * pt = ±pt => - // scalar - 1 = ±1 (mod N) => scalar = 0 or 2. - // In both cases (scalar - 1) / 2 cannot be in the range [0, 2**(m-1)), so we get a - // contradiction. - let (res: G1Point) = fast_ec_add(pt0=pt, pt1=inner_res); - return (pow2=inner_pow2, res=res); - } - - func ec_mul{range_check_ptr}(pt: G1Point, scalar: BigInt3) -> (res: G1Point) { - alloc_locals; - let (pow2_0: G1Point, local res0: G1Point) = ec_mul_inner(pt, scalar.d0, 86); - let (pow2_1: G1Point, local res1: G1Point) = ec_mul_inner(pow2_0, scalar.d1, 86); - let (_, local res2: G1Point) = ec_mul_inner(pow2_1, scalar.d2, 84); - let (res: G1Point) = ec_add(res0, res1); - let (res: G1Point) = ec_add(res, res2); - return (res,); - } - - // CONSTANTS - func g1() -> (res: G1Point) { - return (res=G1Point(BigInt3(1, 0, 0), BigInt3(2, 0, 0))); - } - - func g1_two() -> (res: G1Point) { - return ( - G1Point( - BigInt3(0x71ca8d3c208c16d87cfd3, 0x116da060561765e05aa45a, 0x30644e72e131a029b850), - BigInt3( - 0x138fc7ff3ebf7a5a18a2c4, 0x3e5acaba7029a29a91278d, 0x15ed738c0e0a7c92e7845 - ), - ), - ); - } - - func g1_three() -> (res: G1Point) { - return ( - G1Point( - BigInt3(0x38e679f2d355961915abf0, 0xaf2c6daf4564c57611c56, 0x769bf9ac56bea3ff4023), - BigInt3( - 0x1c5b57cdf1ff3dd9fe2261, 0x2df2342191d4c6798ed02e, 0x2ab799bee0489429554fd - ), - ), - ); - } - - func g1_negone() -> (res: G1Point) { - return ( - G1Point( - BigInt3(0x1, 0x0, 0x0), - BigInt3( - 0x31ca8d3c208c16d87cfd45, 0x16da060561765e05aa45a1, 0x30644e72e131a029b8504 - ), - ), - ); - } - - func g1_negtwo() -> (res: G1Point) { - return ( - G1Point( - BigInt3(0x71ca8d3c208c16d87cfd3, 0x116da060561765e05aa45a, 0x30644e72e131a029b850), - BigInt3( - 0x1e3ac53ce1cc9c7e645a83, 0x187f3b4af14cbb6b191e14, 0x1a76dae6d3272396d0cbe - ), - ), - ); - } - - func g1_negthree() -> (res: G1Point) { - return ( - G1Point( - BigInt3(0x38e679f2d355961915abf0, 0xaf2c6daf4564c57611c56, 0x769bf9ac56bea3ff4023), - BigInt3(0x156f356e2e8cd8fe7edae6, 0x28e7d1e3cfa1978c1b7573, 0x5acb4b400e90c0063006), - ), - ); - } -} diff --git a/src/utils/alt_bn128/bigint.cairo b/src/utils/alt_bn128/bigint.cairo deleted file mode 100644 index 5aef7765d..000000000 --- a/src/utils/alt_bn128/bigint.cairo +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Library copied from https://github.com/tekkac/cairo-alt_bn128 - -// Starkware dependencies -from starkware.cairo.common.cairo_secp.bigint import UnreducedBigInt3, BigInt3 - -// The base of the representation. -const BASE = 2 ** 86; - -// Represents a big integer: sum_i(BASE**i * d_i). -// Note that the limbs (d_i) are NOT restricted to the range [0, BASE) and in particular they -// can be negative. -struct UnreducedBigInt5 { - d0: felt, - d1: felt, - d2: felt, - d3: felt, - d4: felt, -} - -func bigint_mul(x: BigInt3, y: BigInt3) -> (res: UnreducedBigInt5) { - return ( - UnreducedBigInt5( - d0=x.d0 * y.d0, - d1=x.d0 * y.d1 + x.d1 * y.d0, - d2=x.d0 * y.d2 + x.d1 * y.d1 + x.d2 * y.d0, - d3=x.d1 * y.d2 + x.d2 * y.d1, - d4=x.d2 * y.d2, - ), - ); -} - -// Returns a BigInt3 instance whose value is controlled by a prover hint. -// -// Soundness guarantee: each limb is in the range [0, 3 * BASE). -// Completeness guarantee (honest prover): the value is in reduced form and in particular, -// each limb is in the range [0, BASE). -// -// Hint arguments: value. -func nondet_bigint3{range_check_ptr}() -> (res: BigInt3) { - // The result should be at the end of the stack after the function returns. - let res: BigInt3 = [cast(ap + 5, BigInt3*)]; - %{ - from starkware.cairo.common.cairo_secp.secp_utils import split - segments.write_arg(ids.res.address_, split(value)) - %} - // The maximal possible sum of the limbs, assuming each of them is in the range [0, BASE). - const MAX_SUM = 3 * (BASE - 1); - assert [range_check_ptr] = MAX_SUM - (res.d0 + res.d1 + res.d2); - - // Prepare the result at the end of the stack. - tempvar range_check_ptr = range_check_ptr + 4; - [range_check_ptr - 3] = res.d0, ap++; - [range_check_ptr - 2] = res.d1, ap++; - [range_check_ptr - 1] = res.d2, ap++; - static_assert &res + BigInt3.SIZE == ap; - return (res=res); -} diff --git a/tests/end_to_end/EvmPrecompiles/test_evm_precompiles.py b/tests/end_to_end/EvmPrecompiles/test_evm_precompiles.py new file mode 100644 index 000000000..b7c945259 --- /dev/null +++ b/tests/end_to_end/EvmPrecompiles/test_evm_precompiles.py @@ -0,0 +1,121 @@ +import pytest +import pytest_asyncio +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ALT_BN128_PRIME, BNF, BNP +from hypothesis import given, settings +from hypothesis.strategies import integers + +from kakarot_scripts.utils.kakarot import deploy + + +@pytest_asyncio.fixture(scope="package") +async def evm_precompiles(): + return await deploy( + "EvmPrecompiles", + "EvmPrecompiles", + ) + + +def ref_alt_bn128_add(x0, y0, x1, y1): + """ + # ruff: noqa: D401 + Reference implementation of the alt_bn128_add precompile. + Source: https://github.com/ethereum/execution-specs/blob/07f5747a43d62ef7f203d41d77005cb15ca5e434/src/ethereum/cancun/vm/precompiled_contracts/alt_bn128.py#L32-L103. + """ + x0_value = U256.from_signed(x0) + y0_value = U256.from_signed(y0) + x1_value = U256.from_signed(x1) + y1_value = U256.from_signed(y1) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + return [False, 0, 0] + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + return [False, 0, 0] + + p = p0 + p1 + + x_bytes = p.x.to_be_bytes32() + y_bytes = p.y.to_be_bytes32() + + x = Uint(int.from_bytes(x_bytes, "big")) + y = Uint(int.from_bytes(y_bytes, "big")) + + return [True, x, y] + + +def ref_alt_bn128_mul(x0, y0, s): + """ + # ruff: noqa: D401 + Reference implementation of the alt_bn128_mul precompile. + Source: https://github.com/ethereum/execution-specs/blob/07f5747a43d62ef7f203d41d77005cb15ca5e434/src/ethereum/cancun/vm/precompiled_contracts/alt_bn128.py#L32-L103. + """ + x0_value = U256.from_signed(x0) + y0_value = U256.from_signed(y0) + s_value = U256.from_signed(s) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + return [False, 0, 0] + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + return [False, 0, 0] + + p = p0.mul_by(s_value) + + x_bytes = p.x.to_be_bytes32() + y_bytes = p.y.to_be_bytes32() + + x = Uint(int.from_bytes(x_bytes, "big")) + y = Uint(int.from_bytes(y_bytes, "big")) + + return [True, x, y] + + +@pytest.mark.asyncio(scope="package") +@pytest.mark.EvmPrecompiles +class TestEvmPrecompiles: + class TestEcAdd: + @given( + x0=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + y0=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + x1=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + y1=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + ) + @settings(max_examples=10) + async def test_should_return_ec_add_with_coordinates( + self, evm_precompiles, x0, y0, x1, y1 + ): + expected = ref_alt_bn128_add(x0, y0, x1, y1) + result = await evm_precompiles.ecAdd(x0, y0, x1, y1) + assert result == expected + + async def test_should_return_ec_add_point_at_infinity(self, evm_precompiles): + expected = ref_alt_bn128_add(0, 0, 0, 0) + result = await evm_precompiles.ecAdd(0, 0, 0, 0) + assert result == expected + + class TestEcMul: + @given( + x0=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + y0=integers(min_value=0, max_value=ALT_BN128_PRIME - 1), + s=integers(min_value=0, max_value=2**256 - 1), + ) + @settings(max_examples=10) + async def test_should_return_ec_mul_with_coordinates( + self, evm_precompiles, x0, y0, s + ): + expected = ref_alt_bn128_mul(x0, y0, s) + result = await evm_precompiles.ecMul(x0, y0, s) + assert result == expected + + async def test_should_return_ec_mul_point_at_infinity(self, evm_precompiles): + expected = ref_alt_bn128_mul(0, 0, 0) + result = await evm_precompiles.ecMul(0, 0, 0) + assert result == expected diff --git a/tests/src/kakarot/precompiles/test_datacopy.cairo b/tests/src/kakarot/precompiles/test_datacopy.cairo index 467afd040..212103acd 100644 --- a/tests/src/kakarot/precompiles/test_datacopy.cairo +++ b/tests/src/kakarot/precompiles/test_datacopy.cairo @@ -4,7 +4,7 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin from starkware.cairo.common.alloc import alloc from utils.utils import Helpers -from kakarot.precompiles.datacopy import PrecompileDataCopy +from kakarot.precompiles.identity import PrecompileIdentity from tests.utils.helpers import TestHelpers func test__datacopy_impl{ @@ -20,8 +20,8 @@ func test__datacopy_impl{ %} // When - let result = PrecompileDataCopy.run( - PrecompileDataCopy.PRECOMPILE_ADDRESS, calldata_len, calldata + let result = PrecompileIdentity.run( + PrecompileIdentity.PRECOMPILE_ADDRESS, calldata_len, calldata ); TestHelpers.assert_array_equal( diff --git a/tests/src/kakarot/precompiles/test_ec_add.cairo b/tests/src/kakarot/precompiles/test_ec_add.cairo deleted file mode 100644 index 8d756ec82..000000000 --- a/tests/src/kakarot/precompiles/test_ec_add.cairo +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT - -%lang starknet - -// Starkware dependencies -from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin -from starkware.cairo.common.cairo_secp.bigint import BigInt3, bigint_to_uint256, uint256_to_bigint -from starkware.cairo.common.uint256 import Uint256, assert_uint256_eq -from starkware.cairo.common.math import split_felt -from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.alloc import alloc - -// Local dependencies -from utils.utils import Helpers -from utils.alt_bn128.alt_bn128_g1 import ALT_BN128, G1Point -from kakarot.precompiles.ecadd import PrecompileEcAdd -from kakarot.model import model -from kakarot.memory import Memory -from kakarot.constants import Constants -from kakarot.stack import Stack -from kakarot.evm import EVM -from kakarot.instructions.memory_operations import MemoryOperations -from kakarot.instructions.system_operations import SystemOperations, CallHelper, CreateHelper -from tests.utils.helpers import TestHelpers - -const G1POINT_BYTES_LEN = 32; - -func test__ecadd_impl{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* -}() { - // Given - alloc_locals; - local calldata_len: felt; - let (calldata: felt*) = alloc(); - %{ - ids.calldata_len = len(program_input["calldata"]); - segments.write_arg(ids.calldata, program_input["calldata"]); - %} - - let x0: BigInt3 = Helpers.bytes32_to_bigint(calldata); - let y0: BigInt3 = Helpers.bytes32_to_bigint(calldata + G1POINT_BYTES_LEN); - let x1: BigInt3 = Helpers.bytes32_to_bigint(calldata + G1POINT_BYTES_LEN * 2); - let y1: BigInt3 = Helpers.bytes32_to_bigint(calldata + G1POINT_BYTES_LEN * 3); - - // When - let point0: G1Point = G1Point(x0, y0); - let point1: G1Point = G1Point(x1, y1); - let (expected_point: G1Point) = ALT_BN128.ec_add(point0, point1); - let (bytes_expected_x_len, bytes_expected_result: felt*) = Helpers.bigint_to_bytes_array( - expected_point.x - ); - let (bytes_expected_y_len, bytes_expected_y: felt*) = Helpers.bigint_to_bytes_array( - expected_point.y - ); - memcpy(bytes_expected_result + bytes_expected_x_len, bytes_expected_y, bytes_expected_y_len); - let (output_len, output: felt*, gas_used, reverted) = PrecompileEcAdd.run( - PrecompileEcAdd.PRECOMPILE_ADDRESS, calldata_len, calldata - ); - - // Then - TestHelpers.assert_array_equal( - array_0_len=bytes_expected_x_len + bytes_expected_y_len, - array_0=bytes_expected_result, - array_1_len=output_len, - array_1=output, - ); - - return (); -} diff --git a/tests/src/kakarot/precompiles/test_ec_add.py b/tests/src/kakarot/precompiles/test_ec_add.py deleted file mode 100644 index 9c1437925..000000000 --- a/tests/src/kakarot/precompiles/test_ec_add.py +++ /dev/null @@ -1,11 +0,0 @@ -import hypothesis.strategies as st -import pytest -from hypothesis import given, settings - - -@pytest.mark.EC_ADD -class TestEcAdd: - @given(calldata=st.binary(min_size=128, max_size=128)) - @settings(max_examples=5) - def test_ecadd(self, cairo_run, calldata): - cairo_run("test__ecadd_impl", calldata=list(calldata)) diff --git a/tests/src/kakarot/precompiles/test_ec_mul.cairo b/tests/src/kakarot/precompiles/test_ec_mul.cairo deleted file mode 100644 index 25f990099..000000000 --- a/tests/src/kakarot/precompiles/test_ec_mul.cairo +++ /dev/null @@ -1,57 +0,0 @@ -%lang starknet - -from starkware.cairo.common.alloc import alloc -from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin -from starkware.cairo.common.cairo_secp.bigint import BigInt3, bigint_to_uint256, uint256_to_bigint -from starkware.cairo.common.uint256 import Uint256 -from starkware.cairo.common.memcpy import memcpy - -from utils.utils import Helpers -from utils.alt_bn128.alt_bn128_g1 import ALT_BN128, G1Point -from kakarot.precompiles.ecmul import PrecompileEcMul -from tests.utils.helpers import TestHelpers - -const G1POINT_BYTES_LEN = 32; - -func test__ecmul_impl{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* -}() { - // Given - alloc_locals; - - let x: BigInt3 = uint256_to_bigint(Uint256(1, 0)); - let y: BigInt3 = uint256_to_bigint(Uint256(2, 0)); - let scalar: BigInt3 = uint256_to_bigint(Uint256(2, 0)); - let (x_bytes_len, x_bytes: felt*) = Helpers.bigint_to_bytes_array(x); - let (y_bytes_len, y_bytes: felt*) = Helpers.bigint_to_bytes_array(y); - let (scalar_bytes_len, scalar_bytes: felt*) = Helpers.bigint_to_bytes_array(scalar); - - // When - let point: G1Point = G1Point(x, y); - let (expected_point: G1Point) = ALT_BN128.ec_mul(point, scalar); - let (bytes_expected_x_len, bytes_expected_result: felt*) = Helpers.bigint_to_bytes_array( - expected_point.x - ); - let (bytes_expected_y_len, bytes_expected_y: felt*) = Helpers.bigint_to_bytes_array( - expected_point.y - ); - memcpy(bytes_expected_result + bytes_expected_x_len, bytes_expected_y, bytes_expected_y_len); - let input_len = 96; - let (input: felt*) = alloc(); - memcpy(input, x_bytes, x_bytes_len); - memcpy(input + 32, y_bytes, y_bytes_len); - memcpy(input + 64, scalar_bytes, scalar_bytes_len); - let (output_len, output: felt*, gas_used, reverted) = PrecompileEcMul.run( - PrecompileEcMul.PRECOMPILE_ADDRESS, input_len, input - ); - - // Then - TestHelpers.assert_array_equal( - array_0_len=bytes_expected_x_len + bytes_expected_y_len, - array_0=bytes_expected_result, - array_1_len=output_len, - array_1=output, - ); - - return (); -} diff --git a/tests/src/kakarot/precompiles/test_ec_mul.py b/tests/src/kakarot/precompiles/test_ec_mul.py deleted file mode 100644 index b9db12788..000000000 --- a/tests/src/kakarot/precompiles/test_ec_mul.py +++ /dev/null @@ -1,8 +0,0 @@ -import pytest - - -@pytest.mark.EC_MUL -class TestEcMul: - @pytest.mark.slow - def test_ec_mul(self, cairo_run): - cairo_run("test__ecmul_impl") diff --git a/tests/src/kakarot/precompiles/test_precompiles.py b/tests/src/kakarot/precompiles/test_precompiles.py index 489ee596e..289727991 100644 --- a/tests/src/kakarot/precompiles/test_precompiles.py +++ b/tests/src/kakarot/precompiles/test_precompiles.py @@ -28,8 +28,7 @@ class TestEthereumPrecompiles: "address, error_message", [ (0x0, "Kakarot: UnknownPrecompile 0"), - (0x6, "Kakarot: NotImplementedPrecompile 6"), - (0x7, "Kakarot: NotImplementedPrecompile 7"), + (0x5, "Kakarot: NotImplementedPrecompile 5"), (0x8, "Kakarot: NotImplementedPrecompile 8"), (0x0A, "Kakarot: NotImplementedPrecompile 10"), ],