Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable ec_add / ec_mul #1398

Merged
merged 15 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
# 173874367 corresponds to release v0.1.13 of Kakarot SSJ.
KKRT_SSJ_RELEASE_ID = 176384150
enitrat marked this conversation as resolved.
Show resolved Hide resolved
# 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
Expand All @@ -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
Expand Down
11 changes: 7 additions & 4 deletions kakarot_scripts/utils/starknet.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ def get_deployments():

@cache
def get_artifact(contract_name):
# Cairo 0 artifacts
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
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")
)
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ 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"
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"
Expand Down
55 changes: 55 additions & 0 deletions solidity_contracts/src/EvmPrecompiles/EvmPrecompiles.sol
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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 = 1000000;
/// @dev Gas cost for ECMUL call is 6000
uint256 private constant ECMUL_GAS = 1000000;
enitrat marked this conversation as resolved.
Show resolved Hide resolved

/*//////////////////////////////////////////////////////////////
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) {
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
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);
}
}
25 changes: 18 additions & 7 deletions src/kakarot/interpreter.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down
58 changes: 0 additions & 58 deletions src/kakarot/precompiles/ecadd.cairo

This file was deleted.

55 changes: 0 additions & 55 deletions src/kakarot/precompiles/ecmul.cairo

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
}
}
Loading
Loading