Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Implement NativeSyscallHandler::deploy #1106

Merged
merged 16 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 30 additions & 0 deletions .github/workflows/rust-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
lint:
name: Lint with fmt and clippy
runs-on: ubuntu-latest
env:
MLIR_SYS_170_PREFIX: /usr/lib/llvm-17/
TABLEGEN_170_PREFIX: /usr/lib/llvm-17/
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -56,6 +59,33 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: check and free hdd space left
run: |
echo "Listing 20 largest packages"
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 20
df -h
sudo apt-get update
sudo apt-get remove -y '^llvm-.*'
sudo apt-get remove -y 'php.*'
sudo apt-get remove -y '^dotnet-.*'
sudo apt-get remove -y '^temurin-.*'
sudo apt-get remove -y azure-cli google-cloud-cli microsoft-edge-stable google-chrome-stable firefox powershell mono-devel
sudo apt-get autoremove -y
sudo apt-get clean
df -h
echo "Removing large directories"
# deleting 15GB
sudo rm -rf /usr/share/dotnet/
sudo rm -rf /usr/local/lib/android
df -h
- name: add llvm deb repository
uses: myci-actions/add-deb-repo@10
with:
repo: deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main
repo-name: llvm-repo
keys-asc: https://apt.llvm.org/llvm-snapshot.gpg.key
- name: Install LLVM
run: sudo apt-get install llvm-17 llvm-17-dev llvm-17-runtime clang-17 clang-tools-17 lld-17 libpolly-17-dev libmlir-17-dev mlir-17-tools
- name: Install deps
run: make deps
- name: Format
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ clean:
-rm -rf cairo-*.tar

clippy: compile-cairo compile-starknet compile-cairo-1-casm compile-cairo-1-sierra compile-cairo-2-casm compile-cairo-2-sierra
cargo clippy --workspace --all-targets -- -D warnings
cargo clippy --workspace --all-targets --all-features -- -D warnings

test: compile-cairo compile-starknet compile-cairo-1-casm compile-cairo-1-sierra compile-cairo-2-casm compile-cairo-2-sierra
echo "Cairo1 tests"
Expand Down
4 changes: 2 additions & 2 deletions src/syscalls/business_logic_syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ impl<'a, S: StateReader> BusinessLogicSyscallHandler<'a, S> {
contract_address: &Address,
class_hash_bytes: ClassHash,
constructor_calldata: Vec<Felt252>,
remainig_gas: u128,
remaining_gas: u128,
) -> Result<CallResult, StateError> {
let compiled_class = if let Ok(compiled_class) = self
.starknet_storage_state
Expand Down Expand Up @@ -361,7 +361,7 @@ impl<'a, S: StateReader> BusinessLogicSyscallHandler<'a, S> {
EntryPointType::Constructor,
Some(CallType::Call),
None,
remainig_gas,
remaining_gas,
);

let ExecutionResult {
Expand Down
142 changes: 138 additions & 4 deletions src/syscalls/native_syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ use cairo_native::starknet::{
use cairo_vm::felt::Felt252;
use num_traits::Zero;

use crate::definitions::constants::CONSTRUCTOR_ENTRY_POINT_SELECTOR;
use crate::execution::CallResult;
use crate::hash_utils::calculate_contract_address;
use crate::services::api::contract_class_errors::ContractClassError;
use crate::services::api::contract_classes::compiled_class::CompiledClass;
use crate::state::state_api::State;
use crate::utils::felt_to_hash;
use crate::utils::ClassHash;
use crate::{
core::errors::state_errors::StateError,
definitions::block_context::BlockContext,
Expand Down Expand Up @@ -85,12 +93,51 @@ impl<'a, S: StateReader> StarkNetSyscallHandler for NativeSyscallHandler<'a, S>
contract_address_salt: cairo_vm::felt::Felt252,
calldata: &[cairo_vm::felt::Felt252],
deploy_from_zero: bool,
_gas: &mut u128,
gas: &mut u128,
) -> SyscallResult<(cairo_vm::felt::Felt252, Vec<cairo_vm::felt::Felt252>)> {
println!("Called `deploy({class_hash}, {contract_address_salt}, {calldata:?}, {deploy_from_zero})` from MLIR.");
let deployer_address = if deploy_from_zero {
Address::default()
} else {
self.contract_address.clone()
};

let contract_address = Address(
calculate_contract_address(
&contract_address_salt,
&class_hash,
calldata,
deployer_address,
)
.map_err(|_| {
vec![Felt252::from_bytes_be(
b"FAILED_TO_CALCULATE_CONTRACT_ADDRESS",
)]
})?,
);
// Initialize the contract.
let class_hash_bytes: ClassHash = felt_to_hash(&class_hash);

self.starknet_storage_state
.state
.deploy_contract(contract_address.clone(), class_hash_bytes)
.map_err(|_| vec![Felt252::from_bytes_be(b"CONTRACT_ADDRESS_UNAVAILABLE")])?;

let result = self
.execute_constructor_entry_point(
&contract_address,
class_hash_bytes,
calldata.to_vec(),
*gas,
)
.map_err(|_| vec![Felt252::from_bytes_be(b"CONSTRUCTOR_ENTRYPOINT_FAILURE")])?;

Ok((
class_hash + contract_address_salt,
calldata.iter().map(|x| x + &Felt252::new(1)).collect(),
contract_address.0,
result
.retdata
.iter()
.map(|mb| mb.get_int_ref().cloned().unwrap_or_default())
.collect(),
))
}

Expand Down Expand Up @@ -376,3 +423,90 @@ impl<'a, S: StateReader> StarkNetSyscallHandler for NativeSyscallHandler<'a, S>
self.tx_execution_context.version = version;
}
}

impl<'a, S> NativeSyscallHandler<'a, S>
where
S: StateReader,
{
fn execute_constructor_entry_point(
&mut self,
contract_address: &Address,
class_hash_bytes: ClassHash,
constructor_calldata: Vec<Felt252>,
remaining_gas: u128,
) -> Result<CallResult, StateError> {
let compiled_class = if let Ok(compiled_class) = self
.starknet_storage_state
.state
.get_contract_class(&class_hash_bytes)
{
compiled_class
} else {
return Ok(CallResult {
gas_consumed: 0,
is_success: false,
retdata: vec![Felt252::from_bytes_be(b"CLASS_HASH_NOT_FOUND").into()],
});
};

if self.constructor_entry_points_empty(compiled_class)? {
if !constructor_calldata.is_empty() {
return Err(StateError::ConstructorCalldataEmpty());
}

let call_info = CallInfo::empty_constructor_call(
contract_address.clone(),
self.contract_address.clone(),
Some(class_hash_bytes),
);
self.internal_calls.push(call_info.clone());

return Ok(call_info.result());
}

let call = ExecutionEntryPoint::new(
contract_address.clone(),
constructor_calldata,
CONSTRUCTOR_ENTRY_POINT_SELECTOR.clone(),
self.contract_address.clone(),
EntryPointType::Constructor,
Some(CallType::Call),
None,
remaining_gas,
);

let ExecutionResult { call_info, .. } = call
.execute(
self.starknet_storage_state.state,
// TODO: This fields dont make much sense in the Cairo Native context,
// they are only dummy values for the `execute` method.
&BlockContext::default(),
&mut ExecutionResourcesManager::default(),
&mut self.tx_execution_context,
false,
u64::MAX,
)
.map_err(|_| StateError::ExecutionEntryPoint())?;

let call_info = call_info.ok_or(StateError::CustomError("Execution error".to_string()))?;

self.internal_calls.push(call_info.clone());

Ok(call_info.result())
}

fn constructor_entry_points_empty(
&self,
contract_class: CompiledClass,
) -> Result<bool, StateError> {
match contract_class {
CompiledClass::Deprecated(class) => Ok(class
.entry_points_by_type
.get(&EntryPointType::Constructor)
.ok_or(ContractClassError::NoneEntryPointType)?
.is_empty()),
CompiledClass::Casm(class) => Ok(class.entry_points_by_type.constructor.is_empty()),
CompiledClass::Sierra(class) => Ok(class.entry_points_by_type.constructor.is_empty()),
}
}
}
8 changes: 5 additions & 3 deletions starknet_programs/cairo2/deploy.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use starknet::class_hash::ClassHash;

#[starknet::interface]
trait IDeployTest<TContractState> {
fn deploy_test(self: @TContractState, class_hash: felt252, contract_address_salt: felt252) -> starknet::contract_address::ContractAddress;
fn deploy_test(self: @TContractState, class_hash: ClassHash, contract_address_salt: felt252) -> starknet::contract_address::ContractAddress;
}

#[starknet::contract]
Expand All @@ -21,10 +23,10 @@ mod DeployTest {

#[external(v0)]
impl DeployTest of super::IDeployTest<ContractState> {
fn deploy_test(self: @ContractState, class_hash: felt252, contract_address_salt: felt252) -> ContractAddress {
fn deploy_test(self: @ContractState, class_hash: ClassHash, contract_address_salt: felt252) -> ContractAddress {
let mut calldata = ArrayTrait::new();
calldata.append(100);
let (address0, _) = deploy_syscall(class_hash.try_into().unwrap(), contract_address_salt, calldata.span(), false).unwrap();
let (address0, _) = deploy_syscall(class_hash, contract_address_salt, calldata.span(), false).unwrap();
address0
}
}
Expand Down
Loading