Skip to content

Commit

Permalink
feat: ecAdd / ecMul (#880)
Browse files Browse the repository at this point in the history
* feat: ecAdd / ecMul

* fix: gas cost ecMul 6000

* fix: returndata on wrong precompile input

* fmt

* remove custom clone impls in snforge_utils

---------

Co-authored-by: enitrat <[email protected]>
  • Loading branch information
obatirou and enitrat authored Sep 5, 2024
1 parent e452de2 commit 5132b8c
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scarb 2.7.1
starknet-foundry 0.28.0
starknet-foundry 0.30.0
6 changes: 3 additions & 3 deletions Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ dependencies = [
[[package]]
name = "snforge_scarb_plugin"
version = "0.1.0"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.28.0#4dfe39d96690ed6b3d56971512700de3f58288ea"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.30.0#196f06b251926697c3d66800f2a93ae595e76496"

[[package]]
name = "snforge_std"
version = "0.28.0"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.28.0#4dfe39d96690ed6b3d56971512700de3f58288ea"
version = "0.30.0"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.30.0#196f06b251926697c3d66800f2a93ae595e76496"
dependencies = [
"snforge_scarb_plugin",
]
Expand Down
2 changes: 1 addition & 1 deletion crates/alexandria_data_structures/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = "0.1.0"
[dependencies]

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }

[scripts]
test = "snforge test --max-n-steps 4294967295"
Expand Down
2 changes: 1 addition & 1 deletion crates/contracts/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ build-external-contracts = ["openzeppelin::token::erc20::erc20::ERC20"]
name = "contracts"

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }
assert_macros = "0.1.0"
snforge_utils = { path = "../snforge_utils" }

Expand Down
2 changes: 1 addition & 1 deletion crates/evm/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ openzeppelin = { path = "../openzeppelin" }
garaga = { git = "https://github.com/keep-starknet-strange/garaga.git" }

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }
snforge_utils = { path = "../snforge_utils" }
assert_macros = "0.1.0"

Expand Down
18 changes: 4 additions & 14 deletions crates/evm/src/precompiles.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use evm::errors::EVMError;
use evm::model::vm::VM;
use evm::model::vm::VMTrait;
use evm::precompiles::blake2f::Blake2f;
use evm::precompiles::ec_add::EcAdd;
use evm::precompiles::ec_mul::EcMul;
use evm::precompiles::ec_recover::EcRecover;
use evm::precompiles::identity::Identity;
use evm::precompiles::modexp::ModExp;
Expand Down Expand Up @@ -67,20 +69,8 @@ impl PrecompilesImpl of Precompiles {
},
0x04 => { Identity::exec(input)? },
0x05 => { ModExp::exec(input)? },
0x06 => {
// we should never reach this branch!
panic!(
"pre-compile at address {} isn't implemented yet",
precompile_address.address
)
},
0x07 => {
// we should never reach this branch!
panic!(
"pre-compile at address {} isn't implemented yet",
precompile_address.address
)
},
0x06 => { EcAdd::exec(input)? },
0x07 => { EcMul::exec(input)? },
0x08 => {
// we should never reach this branch!
panic!(
Expand Down
45 changes: 45 additions & 0 deletions crates/evm/src/precompiles/ec_add.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,51 @@ use evm::precompiles::Precompile;
use garaga::core::circuit::AddInputResultTrait2;
use garaga::utils::u384_eq_zero;
use utils::helpers::{U256Trait, ToBytes, FromBytes};
use utils::helpers::{load_word, u256_to_bytes_array};


const BASE_COST: u128 = 150;
const U256_BYTES_LEN: usize = 32;

impl EcAdd of Precompile {
#[inline(always)]
fn address() -> EthAddress {
EthAddress { address: 0x6 }
}

fn exec(mut input: Span<u8>) -> Result<(u128, Span<u8>), EVMError> {
let gas = BASE_COST;

let x1_bytes = *(input.multi_pop_front::<32>().unwrap());
let x1: u256 = load_word(U256_BYTES_LEN, x1_bytes.unbox().span());

let y1_bytes = *(input.multi_pop_front::<32>().unwrap());
let y1: u256 = load_word(U256_BYTES_LEN, y1_bytes.unbox().span());

let x2_bytes = *(input.multi_pop_front::<32>().unwrap());
let x2: u256 = load_word(U256_BYTES_LEN, x2_bytes.unbox().span());

let y2_bytes = *(input.multi_pop_front::<32>().unwrap());
let y2: u256 = load_word(U256_BYTES_LEN, y2_bytes.unbox().span());

let (x, y) = match ec_add(x1, y1, x2, y2) {
Option::Some((x, y)) => { (x, y) },
Option::None => {
return Result::Err(EVMError::InvalidParameter('invalid ec_add parameters'));
},
};

let mut result_bytes = array![];
// Append x to the result bytes.
let x_bytes = x.to_be_bytes_padded();
result_bytes.append_span(x_bytes);
// Append y to the result bytes.
let y_bytes = y.to_be_bytes_padded();
result_bytes.append_span(y_bytes);

return Result::Ok((gas, result_bytes.span()));
}
}


fn ec_add(x1: u256, y1: u256, x2: u256, y2: u256) -> Option<(u256, u256)> {
Expand Down
41 changes: 39 additions & 2 deletions crates/evm/src/precompiles/ec_mul.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,48 @@ use evm::precompiles::ec_add::{
};
use garaga::core::circuit::AddInputResultTrait2;
use garaga::utils::u384_eq_zero;
use utils::helpers::{U256Trait, ToBytes, FromBytes};
use utils::helpers::{load_word, u256_to_bytes_array, U256Trait, ToBytes, FromBytes};

// const BN254_ORDER: u256 = 0x30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000001;

const BASE_COST: u128 = 6000;
const U256_BYTES_LEN: usize = 32;

impl EcMul of Precompile {
fn address() -> EthAddress {
EthAddress { address: 0x7 }
}

fn exec(mut input: Span<u8>) -> Result<(u128, Span<u8>), EVMError> {
let gas = BASE_COST;

let x1_bytes = *(input.multi_pop_front::<32>().unwrap());
let x1: u256 = load_word(U256_BYTES_LEN, x1_bytes.unbox().span());

let y1_bytes = *(input.multi_pop_front::<32>().unwrap());
let y1: u256 = load_word(U256_BYTES_LEN, y1_bytes.unbox().span());

let s_bytes = *(input.multi_pop_front::<32>().unwrap());
let s: u256 = load_word(U256_BYTES_LEN, s_bytes.unbox().span());

let (x, y) = match ec_mul(x1, y1, s) {
Option::Some((x, y)) => { (x, y) },
Option::None => {
return Result::Err(EVMError::InvalidParameter('invalid ec_mul parameters'));
},
};

// Append x and y to the result bytes.
let mut result_bytes = array![];
let x_bytes = x.to_be_bytes_padded();
result_bytes.append_span(x_bytes);
let y_bytes = y.to_be_bytes_padded();
result_bytes.append_span(y_bytes);

return Result::Ok((gas, result_bytes.span()));
}
}

// Returns Option::None in case of error.
fn ec_mul(x1: u256, y1: u256, s: u256) -> Option<(u256, u256)> {
if x1 == 0 && y1 == 0 {
Expand Down Expand Up @@ -100,4 +138,3 @@ fn ec_mul_inner(pt: (u384, u384), mut bits: Array<felt252>) -> Option<(u384, u38

pt
}

2 changes: 1 addition & 1 deletion crates/openzeppelin/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ starknet.workspace = true
fmt.workspace = true

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }

[scripts]
test = "snforge test --max-n-steps 4294967295"
Expand Down
2 changes: 1 addition & 1 deletion crates/snforge_utils/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ starknet = "2.7.1"
evm = { path = "../evm" }

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.30.0" }

[[target.starknet-contract]]
sierra = true
Expand Down
61 changes: 0 additions & 61 deletions crates/snforge_utils/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,67 +18,6 @@ pub mod snforge_utils {
get_call_trace, CallTrace, CallEntryPoint, CallResult, EntryPointType, CallType, CallFailure
};

impl CloneEntryPointType of Clone<EntryPointType> {
fn clone(self: @EntryPointType) -> EntryPointType {
match self {
EntryPointType::Constructor => EntryPointType::Constructor,
EntryPointType::External => EntryPointType::External,
EntryPointType::L1Handler => EntryPointType::L1Handler,
}
}
}

impl CloneCallEntryPoint of Clone<CallEntryPoint> {
fn clone(self: @CallEntryPoint) -> CallEntryPoint {
CallEntryPoint {
entry_point_type: self.entry_point_type.clone(),
entry_point_selector: self.entry_point_selector.clone(),
calldata: self.calldata.clone(),
contract_address: self.contract_address.clone(),
caller_address: self.caller_address.clone(),
call_type: self.call_type.clone(),
}
}
}

impl CloneCallType of Clone<CallType> {
fn clone(self: @CallType) -> CallType {
match self {
CallType::Call => CallType::Call,
CallType::Delegate => CallType::Delegate,
}
}
}

impl CloneCallResult of Clone<CallResult> {
fn clone(self: @CallResult) -> CallResult {
match self {
CallResult::Success(val) => CallResult::Success(val.clone()),
CallResult::Failure(val) => CallResult::Failure(val.clone()),
}
}
}

impl CloneCallFailure of Clone<CallFailure> {
fn clone(self: @CallFailure) -> CallFailure {
match self {
CallFailure::Panic(val) => CallFailure::Panic(val.clone()),
CallFailure::Error(val) => CallFailure::Error(val.clone()),
}
}
}


impl CloneCallTrace of Clone<CallTrace> {
fn clone(self: @CallTrace) -> CallTrace {
CallTrace {
entry_point: self.entry_point.clone(),
nested_calls: self.nested_calls.clone(),
result: self.result.clone(),
}
}
}

pub fn is_called(contract_address: ContractAddress, selector: felt252) -> bool {
let call_trace = get_call_trace();

Expand Down
2 changes: 1 addition & 1 deletion crates/utils/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ alexandria_data_structures = { path = "../alexandria_data_structures" }
fmt.workspace = true

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.28.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }

[scripts]
test = "snforge test --max-n-steps 4294967295"
Expand Down

0 comments on commit 5132b8c

Please sign in to comment.