Skip to content

Commit

Permalink
[0.13] Update get_execution_info syscall (lambdaclass#1206)
Browse files Browse the repository at this point in the history
* Add GasPricess & FeeTokenAddresses structs

* Update code

* RpcStateReader::get_gas_price fetch both

* Update code

* Clippy

* Fix comment

* Add VersionSpecificAccountTxFields struct

* Integrate into TransactionExecutionContext

* Replace max_fee field with account_tx_fields for InvokeFunction tx

* Check tx account fields version when creating Invoke tx

* Replace max_fee field with account_tx_fields for DeclareV3 tx

* Replace max_fee field with account_tx_fields for DeployAccount tx

* Update get_transaction_context for Txs not affected by this change

* Fixes

* Fixes

* Fixes

* Fix handling of ignore_max_fee

* Improve placeholder method

* Handle TODOs

* Implement get_onchain_data_cost

* Refactor

* Generalize fn

* Start implementing check_fee_bounds

* Finish implementing check_fee_bounds

* Replace old code

* Fixes

* Implement FeeType for VersionSpecificAccountTxFields

* Update other txs

* Clippy

* Add test

* Simplify

* Move test

* Update max_fee used

* Allocate version specific info

* Fix

* Clippy

* Update makefile cairo 2 version to match toml version

* Add tests for contract using get_execution_info_v2 syscall

* Add test contract

* Add newline at end of file

* Fix typo in contract

* Conditionally ignore broken tests

* Use cairo 1 contracts when running with cairo_1_test feature

* Revert "Use cairo 1 contracts when running with cairo_1_test feature"

This reverts commit e588c45.

* Remove conditional from ignore

* Ignore more tests

* Update test values

* Un-ignore no-longer-broken tests

* Revert "Un-ignore no-longer-broken tests"

This reverts commit c1fa88b.

* Fix merge

* Implement get_execution_v2 for the NativeSyscallHandler + Un-ignore tests
  • Loading branch information
fmoletta authored Feb 6, 2024
1 parent 64e178a commit 15a1e6e
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ $(CAIRO_2_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_2_CONTRACTS_TEST_DIR)/%.sierra
compile-cairo-2-sierra: $(CAIRO_2_COMPILED_SIERRA_CONTRACTS)
compile-cairo-2-casm: $(CAIRO_2_COMPILED_CASM_CONTRACTS)

CAIRO_2_VERSION=2.2.0
CAIRO_2_VERSION=2.4.2

cairo-repo-2-dir = cairo2
cairo-repo-2-dir-macos = cairo2-macos
Expand Down
103 changes: 97 additions & 6 deletions src/syscalls/business_logic_syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ use cairo_vm::{
};
use lazy_static::lazy_static;
use num_traits::{One, ToPrimitive, Zero};
use std::{collections::HashMap, ops::Add};
use std::{
collections::HashMap,
ops::{Add, Sub},
};

#[cfg(feature = "cairo-native")]
use {
Expand Down Expand Up @@ -749,16 +752,20 @@ impl<'a, S: StateReader, C: ContractClassCache> BusinessLogicSyscallHandler<'a,

// Allocate tx info
let tx_info = &self.tx_execution_context;
let tx_info_data = vec![
let mut tx_info_data = vec![
MaybeRelocatable::from(&tx_info.version),
MaybeRelocatable::from(&tx_info.account_contract_address.0),
MaybeRelocatable::from(Felt252::from(tx_info.account_tx_fields.max_fee())),
MaybeRelocatable::from(Felt252::from(
tx_info.account_tx_fields.max_fee_for_execution_info(),
)),
signature_start_ptr.into(),
signature_end_ptr.into(),
MaybeRelocatable::from(&tx_info.transaction_hash),
MaybeRelocatable::from(&self.block_context.starknet_os_config.chain_id),
MaybeRelocatable::from(&tx_info.nonce),
];
self.allocate_version_specific_tx_info(vm, &mut tx_info_data)?;

let tx_info_ptr = self.allocate_segment(vm, tx_info_data)?;

// Allocate execution_info
Expand All @@ -775,6 +782,74 @@ impl<'a, S: StateReader, C: ContractClassCache> BusinessLogicSyscallHandler<'a,
Ok(execution_info_ptr)
}

fn allocate_version_specific_tx_info(
&mut self,
vm: &mut VirtualMachine,
tx_info_data: &mut Vec<MaybeRelocatable>,
) -> Result<(), SyscallHandlerError> {
match self.tx_execution_context.account_tx_fields.clone() {
crate::transaction::VersionSpecificAccountTxFields::Deprecated(_) => {
tx_info_data.extend_from_slice(&[
Felt252::ZERO.into(), // Resource Bounds (start ptr).
Felt252::ZERO.into(), // Resource Bounds (end ptr).
Felt252::ZERO.into(), // Tip.
Felt252::ZERO.into(), // Paymaster Data (start ptr).
Felt252::ZERO.into(), // Paymaster Data (end ptr).
Felt252::ZERO.into(), // Nonce DA mode.
Felt252::ZERO.into(), // Fee DA mode.
Felt252::ZERO.into(), // Account deployment Data (start ptr).
Felt252::ZERO.into(), // Account deployment Data (end ptr).
])
}
crate::transaction::VersionSpecificAccountTxFields::Current(fields) => {
// Allocate resource bounds
lazy_static! {
static ref L1_GAS: Felt252 = Felt252::from_hex(
"0x00000000000000000000000000000000000000000000000000004c315f474153"
)
.unwrap();
static ref L2_GAS: Felt252 = Felt252::from_hex(
"0x00000000000000000000000000000000000000000000000000004c325f474153"
)
.unwrap();
};
let mut resource_bounds_data = vec![
*L1_GAS,
fields.l1_resource_bounds.max_amount.into(),
fields.l1_resource_bounds.max_price_per_unit.into(),
];
if let Some(ref resource_bounds) = fields.l2_resource_bounds {
resource_bounds_data.extend_from_slice(&[
*L2_GAS,
resource_bounds.max_amount.into(),
resource_bounds.max_price_per_unit.into(),
])
}
let (resource_bounds_start_ptr, resource_bounds_end_ptr) =
self.allocate_felt_segment(vm, &resource_bounds_data)?;
// Allocate paymaster data
let (paymaster_data_start_ptr, paymaster_data_end_ptr) =
self.allocate_felt_segment(vm, &fields.paymaster_data)?;
// Allocate account deployment data
let (account_deployment_start_ptr, account_deployment_end_ptr) =
self.allocate_felt_segment(vm, &fields.account_deployment_data)?;
// Extend tx_info_data with version specific data
tx_info_data.extend_from_slice(&[
resource_bounds_start_ptr.into(), // Resource Bounds (start ptr).
resource_bounds_end_ptr.into(), // Resource Bounds (end ptr).
Felt252::from(fields.tip).into(), // Tip.
paymaster_data_start_ptr.into(), // Paymaster Data (start ptr).
paymaster_data_end_ptr.into(), // Paymaster Data (end ptr).
Into::<Felt252>::into(fields.nonce_data_availability_mode).into(), // Nonce DA mode.
Into::<Felt252>::into(fields.fee_data_availability_mode).into(), // Fee DA mode.
account_deployment_start_ptr.into(), // Account deployment Data (start ptr).
account_deployment_end_ptr.into(), // Account deployment Data (end ptr).
])
}
}
Ok(())
}

fn get_execution_info(
&mut self,
vm: &mut VirtualMachine,
Expand Down Expand Up @@ -995,14 +1070,30 @@ impl<'a, S: StateReader, C: ContractClassCache> BusinessLogicSyscallHandler<'a,
data: Vec<MaybeRelocatable>,
) -> Result<Relocatable, SyscallHandlerError> {
let segment_start = vm.add_memory_segment();
let segment_end = vm.write_arg(segment_start, &data)?;
let sub = segment_end.sub(&segment_start.to_owned().into())?;
let segment = (segment_start.to_owned(), sub);
let segment_end = vm.load_data(segment_start, &data)?;
let sub = segment_end.sub(segment_start)?;
let segment = (segment_start.to_owned(), sub.into());
self.read_only_segments.push(segment);

Ok(segment_start)
}

/// Allocate a segment in memory.
/// Returns start and end ptrs for the segment
pub(crate) fn allocate_felt_segment(
&mut self,
vm: &mut VirtualMachine,
data: &[Felt252],
) -> Result<(Relocatable, Relocatable), SyscallHandlerError> {
let segment_start = vm.add_memory_segment();
let segment_end = vm.load_data(segment_start, &data.iter().map(|f| f.into()).collect())?;
let sub = segment_end.sub(segment_start)?;
let segment = (segment_start.to_owned(), sub.into());
self.read_only_segments.push(segment);

Ok((segment_start, segment_end))
}

/// Sends a message from L2 to L1, including the destination address and payload.
fn send_message_to_l1(
&mut self,
Expand Down
80 changes: 77 additions & 3 deletions src/syscalls/native_syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::{
utils::{felt_to_hash, Address, ClassHash},
ContractClassCache, EntryPointType,
};
use cairo_native::starknet::{ResourceBounds, TxV2Info};
use cairo_native::{
cache::ProgramCache,
starknet::{
Expand Down Expand Up @@ -124,7 +125,10 @@ impl<'a, 'cache, S: StateReader, C: ContractClassCache> StarkNetSyscallHandler
tx_info: TxInfo {
version: self.tx_execution_context.version,
account_contract_address: self.tx_execution_context.account_contract_address.0,
max_fee: self.tx_execution_context.account_tx_fields.max_fee(),
max_fee: self
.tx_execution_context
.account_tx_fields
.max_fee_for_execution_info(),
signature: self.tx_execution_context.signature.clone(),
transaction_hash: self.tx_execution_context.transaction_hash,
chain_id: self.block_context.starknet_os_config.chain_id,
Expand Down Expand Up @@ -465,9 +469,79 @@ impl<'a, 'cache, S: StateReader, C: ContractClassCache> StarkNetSyscallHandler

fn get_execution_info_v2(
&mut self,
_: &mut u128,
gas: &mut u128,
) -> Result<ExecutionInfoV2, Vec<cairo_vm::Felt252>> {
todo!()
tracing::debug!("Called `get_execution_info_v2()` from Cairo Native");

self.handle_syscall_request(gas, "get_execution_info")?;

lazy_static::lazy_static! {
static ref L1_GAS: Felt252 = Felt252::from_hex(
"0x00000000000000000000000000000000000000000000000000004c315f474153"
)
.unwrap();
static ref L2_GAS: Felt252 = Felt252::from_hex(
"0x00000000000000000000000000000000000000000000000000004c325f474153"
)
.unwrap();
}

let mut resource_bounds = vec![];
let mut tip = 0;
let mut paymaster_data = vec![];
let mut nonce_data_availability_mode: u32 = 0;
let mut fee_data_availability_mode: u32 = 0;
let mut account_deployment_data = vec![];
if let VersionSpecificAccountTxFields::Current(fields) =
&self.tx_execution_context.account_tx_fields
{
resource_bounds.push(ResourceBounds {
resource: *L1_GAS,
max_amount: fields.l1_resource_bounds.max_amount,
max_price_per_unit: fields.l1_resource_bounds.max_price_per_unit,
});
if let Some(bounds) = &fields.l2_resource_bounds {
resource_bounds.push(ResourceBounds {
resource: *L2_GAS,
max_amount: bounds.max_amount,
max_price_per_unit: bounds.max_price_per_unit,
});
}
tip = fields.tip as u128;
paymaster_data = fields.paymaster_data.clone();
account_deployment_data = fields.account_deployment_data.clone();
nonce_data_availability_mode = fields.nonce_data_availability_mode.into();
fee_data_availability_mode = fields.fee_data_availability_mode.into();
}

Ok(ExecutionInfoV2 {
block_info: BlockInfo {
block_number: self.block_context.block_info.block_number,
block_timestamp: self.block_context.block_info.block_timestamp,
sequencer_address: self.block_context.block_info.sequencer_address.0,
},
tx_info: TxV2Info {
version: self.tx_execution_context.version,
account_contract_address: self.tx_execution_context.account_contract_address.0,
max_fee: self
.tx_execution_context
.account_tx_fields
.max_fee_for_execution_info(),
signature: self.tx_execution_context.signature.clone(),
transaction_hash: self.tx_execution_context.transaction_hash,
chain_id: self.block_context.starknet_os_config.chain_id,
nonce: self.tx_execution_context.nonce,
resource_bounds,
tip,
paymaster_data,
nonce_data_availability_mode,
fee_data_availability_mode,
account_deployment_data,
},
caller_address: self.caller_address.0,
contract_address: self.contract_address.0,
entry_point_selector: self.entry_point_selector,
})
}

fn secp256k1_add(
Expand Down
25 changes: 25 additions & 0 deletions src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,15 @@ impl From<starknet_api::data_availability::DataAvailabilityMode> for DataAvailab
}
}

impl From<DataAvailabilityMode> for Felt252 {
fn from(val: DataAvailabilityMode) -> Self {
match val {
DataAvailabilityMode::L1 => Felt252::ZERO,
DataAvailabilityMode::L2 => Felt252::ONE,
}
}
}

impl From<DataAvailabilityMode> for u64 {
fn from(val: DataAvailabilityMode) -> Self {
match val {
Expand All @@ -341,6 +350,15 @@ impl From<DataAvailabilityMode> for u64 {
}
}

impl From<DataAvailabilityMode> for u32 {
fn from(val: DataAvailabilityMode) -> Self {
match val {
DataAvailabilityMode::L1 => 0,
DataAvailabilityMode::L2 => 1,
}
}
}

#[derive(Clone, Debug, Default)]
pub struct ResourceBounds {
pub max_amount: u64,
Expand Down Expand Up @@ -395,6 +413,13 @@ impl VersionSpecificAccountTxFields {
}
}

pub(crate) fn max_fee_for_execution_info(&self) -> u128 {
match self {
Self::Deprecated(max_fee) => *max_fee,
Self::Current(_) => 0,
}
}

pub fn fee_type(&self) -> FeeType {
match self {
Self::Deprecated(_) => FeeType::Eth,
Expand Down
87 changes: 87 additions & 0 deletions starknet_programs/cairo2/get_execution_info_v2.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use core::starknet::contract_address::ContractAddress;

#[starknet::interface]
trait IGetExecutionInfo<TContractState> {
fn get_info(self: @TContractState) -> (ContractAddress, ContractAddress, ContractAddress, ContractAddress);
}

#[starknet::contract]
mod GetExecutionInfo {
use starknet::info::get_execution_info;
use starknet::info::v2::ExecutionInfo;
use core::starknet::contract_address::ContractAddress;
use box::BoxTrait;
use array::SpanTrait;

#[storage]
struct Storage {
}

#[external(v0)]
impl GetExecutionInfo of super::IGetExecutionInfo<ContractState> {
fn get_info(self: @ContractState) -> (ContractAddress, ContractAddress, ContractAddress, ContractAddress) {
let info = get_execution_info().unbox();
let block_info = info.block_info.unbox();
let tx_info = info.tx_info.unbox();

let block_number = block_info.block_number;
let block_timestamp = block_info.block_timestamp;
let sequencer_address = block_info.sequencer_address;

let version = tx_info.version;
let account_contract_address = tx_info.account_contract_address;
let max_fee = tx_info.max_fee;
let signature = tx_info.signature;
let transaction_hash = tx_info.transaction_hash;
let chain_id = tx_info.chain_id;
let nonce = tx_info.nonce;

let caller_address = info.caller_address;
let contract_address = info.contract_address;
let entry_point_selector = info.entry_point_selector;

// V2 fields

let resource_bounds = tx_info.resource_bounds;
let tip = tx_info.tip;
let paymaster_data = tx_info.paymaster_data;
let nonce_da_mode = tx_info.nonce_data_availability_mode;
let fee_da_mode = tx_info.fee_data_availability_mode;
let account_deployment_data = tx_info.account_deployment_data;

assert(block_number == 0, 'Wrong Block Number');
assert(block_timestamp == 0, 'Wrong Block Timestamp');
assert(version == 1, 'Wrong Version');
assert(max_fee == 0, 'Wrong max fee');
assert(transaction_hash == 0, 'Wrong Tx Hash');
assert(chain_id == 1536727068981429685321, 'Wrong Chain Id');
assert(nonce == 10, 'Wrong Nonce');
assert(entry_point_selector == 1583979555264088613757654119588925070177786702073426169970015447448454297318, 'Wrong Entrypoint Selector');
assert(*signature.at(0) == 22, 'Wrong Signature');
assert(*signature.at(1) == 33, 'Wrong Signature');
assert(signature.len() == 2, 'Wrong Signature len');
assert(*resource_bounds.at(0).resource == 83774935613779, 'Wrong L1 gas resource name');
assert(*resource_bounds.at(0).max_amount == 30, 'Wrong L1 gas max amount');
assert(*resource_bounds.at(0).max_price_per_unit == 15, 'Wrong L1 gas max price per unit');
assert(*resource_bounds.at(1).resource== 83779230581075, 'Wrong L1 gas resource name');
assert(*resource_bounds.at(1).max_amount == 10, 'Wrong L2 gas max amount');
assert(*resource_bounds.at(1).max_price_per_unit == 5, 'Wrong L2 gas max price per unit');
assert(tip == 3, 'Wrong Tip');
assert(*paymaster_data.at(0) == 6, 'Wrong Paymaster Data');
assert(*paymaster_data.at(1) == 17, 'Wrong Paymaster Data');
assert(paymaster_data.len() == 2, 'Wrong Paymaster Data len');
assert(nonce_da_mode == 0, 'Wrong Nonce DA Mode');
assert(fee_da_mode == 1, 'Wrong Fee DA Mode');
assert(*account_deployment_data.at(0) == 7, 'Wrong Acc. Deployment Data');
assert(*account_deployment_data.at(1) == 18, 'Wrong Acc. Deployment Data');
assert(account_deployment_data.len() == 2, 'Wrong Acc. Deployment Data len');

return (
sequencer_address,
account_contract_address,
caller_address,
contract_address
);
}
}
}
2 changes: 1 addition & 1 deletion starknet_programs/cairo2/math_lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[starnet::interface]
#[starknet::interface]
trait IMath<TContractState> {
fn square_root(ref self: TContractState, n: felt252) -> felt252;
}
Expand Down
Loading

0 comments on commit 15a1e6e

Please sign in to comment.