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

Commit 15a1e6e

Browse files
authored
[0.13] Update get_execution_info syscall (#1206)
* 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
1 parent 64e178a commit 15a1e6e

File tree

7 files changed

+415
-13
lines changed

7 files changed

+415
-13
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ $(CAIRO_2_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_2_CONTRACTS_TEST_DIR)/%.sierra
123123
compile-cairo-2-sierra: $(CAIRO_2_COMPILED_SIERRA_CONTRACTS)
124124
compile-cairo-2-casm: $(CAIRO_2_COMPILED_CASM_CONTRACTS)
125125

126-
CAIRO_2_VERSION=2.2.0
126+
CAIRO_2_VERSION=2.4.2
127127

128128
cairo-repo-2-dir = cairo2
129129
cairo-repo-2-dir-macos = cairo2-macos

src/syscalls/business_logic_syscall_handler.rs

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ use cairo_vm::{
4949
};
5050
use lazy_static::lazy_static;
5151
use num_traits::{One, ToPrimitive, Zero};
52-
use std::{collections::HashMap, ops::Add};
52+
use std::{
53+
collections::HashMap,
54+
ops::{Add, Sub},
55+
};
5356

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

750753
// Allocate tx info
751754
let tx_info = &self.tx_execution_context;
752-
let tx_info_data = vec![
755+
let mut tx_info_data = vec![
753756
MaybeRelocatable::from(&tx_info.version),
754757
MaybeRelocatable::from(&tx_info.account_contract_address.0),
755-
MaybeRelocatable::from(Felt252::from(tx_info.account_tx_fields.max_fee())),
758+
MaybeRelocatable::from(Felt252::from(
759+
tx_info.account_tx_fields.max_fee_for_execution_info(),
760+
)),
756761
signature_start_ptr.into(),
757762
signature_end_ptr.into(),
758763
MaybeRelocatable::from(&tx_info.transaction_hash),
759764
MaybeRelocatable::from(&self.block_context.starknet_os_config.chain_id),
760765
MaybeRelocatable::from(&tx_info.nonce),
761766
];
767+
self.allocate_version_specific_tx_info(vm, &mut tx_info_data)?;
768+
762769
let tx_info_ptr = self.allocate_segment(vm, tx_info_data)?;
763770

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

785+
fn allocate_version_specific_tx_info(
786+
&mut self,
787+
vm: &mut VirtualMachine,
788+
tx_info_data: &mut Vec<MaybeRelocatable>,
789+
) -> Result<(), SyscallHandlerError> {
790+
match self.tx_execution_context.account_tx_fields.clone() {
791+
crate::transaction::VersionSpecificAccountTxFields::Deprecated(_) => {
792+
tx_info_data.extend_from_slice(&[
793+
Felt252::ZERO.into(), // Resource Bounds (start ptr).
794+
Felt252::ZERO.into(), // Resource Bounds (end ptr).
795+
Felt252::ZERO.into(), // Tip.
796+
Felt252::ZERO.into(), // Paymaster Data (start ptr).
797+
Felt252::ZERO.into(), // Paymaster Data (end ptr).
798+
Felt252::ZERO.into(), // Nonce DA mode.
799+
Felt252::ZERO.into(), // Fee DA mode.
800+
Felt252::ZERO.into(), // Account deployment Data (start ptr).
801+
Felt252::ZERO.into(), // Account deployment Data (end ptr).
802+
])
803+
}
804+
crate::transaction::VersionSpecificAccountTxFields::Current(fields) => {
805+
// Allocate resource bounds
806+
lazy_static! {
807+
static ref L1_GAS: Felt252 = Felt252::from_hex(
808+
"0x00000000000000000000000000000000000000000000000000004c315f474153"
809+
)
810+
.unwrap();
811+
static ref L2_GAS: Felt252 = Felt252::from_hex(
812+
"0x00000000000000000000000000000000000000000000000000004c325f474153"
813+
)
814+
.unwrap();
815+
};
816+
let mut resource_bounds_data = vec![
817+
*L1_GAS,
818+
fields.l1_resource_bounds.max_amount.into(),
819+
fields.l1_resource_bounds.max_price_per_unit.into(),
820+
];
821+
if let Some(ref resource_bounds) = fields.l2_resource_bounds {
822+
resource_bounds_data.extend_from_slice(&[
823+
*L2_GAS,
824+
resource_bounds.max_amount.into(),
825+
resource_bounds.max_price_per_unit.into(),
826+
])
827+
}
828+
let (resource_bounds_start_ptr, resource_bounds_end_ptr) =
829+
self.allocate_felt_segment(vm, &resource_bounds_data)?;
830+
// Allocate paymaster data
831+
let (paymaster_data_start_ptr, paymaster_data_end_ptr) =
832+
self.allocate_felt_segment(vm, &fields.paymaster_data)?;
833+
// Allocate account deployment data
834+
let (account_deployment_start_ptr, account_deployment_end_ptr) =
835+
self.allocate_felt_segment(vm, &fields.account_deployment_data)?;
836+
// Extend tx_info_data with version specific data
837+
tx_info_data.extend_from_slice(&[
838+
resource_bounds_start_ptr.into(), // Resource Bounds (start ptr).
839+
resource_bounds_end_ptr.into(), // Resource Bounds (end ptr).
840+
Felt252::from(fields.tip).into(), // Tip.
841+
paymaster_data_start_ptr.into(), // Paymaster Data (start ptr).
842+
paymaster_data_end_ptr.into(), // Paymaster Data (end ptr).
843+
Into::<Felt252>::into(fields.nonce_data_availability_mode).into(), // Nonce DA mode.
844+
Into::<Felt252>::into(fields.fee_data_availability_mode).into(), // Fee DA mode.
845+
account_deployment_start_ptr.into(), // Account deployment Data (start ptr).
846+
account_deployment_end_ptr.into(), // Account deployment Data (end ptr).
847+
])
848+
}
849+
}
850+
Ok(())
851+
}
852+
778853
fn get_execution_info(
779854
&mut self,
780855
vm: &mut VirtualMachine,
@@ -995,14 +1070,30 @@ impl<'a, S: StateReader, C: ContractClassCache> BusinessLogicSyscallHandler<'a,
9951070
data: Vec<MaybeRelocatable>,
9961071
) -> Result<Relocatable, SyscallHandlerError> {
9971072
let segment_start = vm.add_memory_segment();
998-
let segment_end = vm.write_arg(segment_start, &data)?;
999-
let sub = segment_end.sub(&segment_start.to_owned().into())?;
1000-
let segment = (segment_start.to_owned(), sub);
1073+
let segment_end = vm.load_data(segment_start, &data)?;
1074+
let sub = segment_end.sub(segment_start)?;
1075+
let segment = (segment_start.to_owned(), sub.into());
10011076
self.read_only_segments.push(segment);
10021077

10031078
Ok(segment_start)
10041079
}
10051080

1081+
/// Allocate a segment in memory.
1082+
/// Returns start and end ptrs for the segment
1083+
pub(crate) fn allocate_felt_segment(
1084+
&mut self,
1085+
vm: &mut VirtualMachine,
1086+
data: &[Felt252],
1087+
) -> Result<(Relocatable, Relocatable), SyscallHandlerError> {
1088+
let segment_start = vm.add_memory_segment();
1089+
let segment_end = vm.load_data(segment_start, &data.iter().map(|f| f.into()).collect())?;
1090+
let sub = segment_end.sub(segment_start)?;
1091+
let segment = (segment_start.to_owned(), sub.into());
1092+
self.read_only_segments.push(segment);
1093+
1094+
Ok((segment_start, segment_end))
1095+
}
1096+
10061097
/// Sends a message from L2 to L1, including the destination address and payload.
10071098
fn send_message_to_l1(
10081099
&mut self,

src/syscalls/native_syscall_handler.rs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::{
2424
utils::{felt_to_hash, Address, ClassHash},
2525
ContractClassCache, EntryPointType,
2626
};
27+
use cairo_native::starknet::{ResourceBounds, TxV2Info};
2728
use cairo_native::{
2829
cache::ProgramCache,
2930
starknet::{
@@ -124,7 +125,10 @@ impl<'a, 'cache, S: StateReader, C: ContractClassCache> StarkNetSyscallHandler
124125
tx_info: TxInfo {
125126
version: self.tx_execution_context.version,
126127
account_contract_address: self.tx_execution_context.account_contract_address.0,
127-
max_fee: self.tx_execution_context.account_tx_fields.max_fee(),
128+
max_fee: self
129+
.tx_execution_context
130+
.account_tx_fields
131+
.max_fee_for_execution_info(),
128132
signature: self.tx_execution_context.signature.clone(),
129133
transaction_hash: self.tx_execution_context.transaction_hash,
130134
chain_id: self.block_context.starknet_os_config.chain_id,
@@ -465,9 +469,79 @@ impl<'a, 'cache, S: StateReader, C: ContractClassCache> StarkNetSyscallHandler
465469

466470
fn get_execution_info_v2(
467471
&mut self,
468-
_: &mut u128,
472+
gas: &mut u128,
469473
) -> Result<ExecutionInfoV2, Vec<cairo_vm::Felt252>> {
470-
todo!()
474+
tracing::debug!("Called `get_execution_info_v2()` from Cairo Native");
475+
476+
self.handle_syscall_request(gas, "get_execution_info")?;
477+
478+
lazy_static::lazy_static! {
479+
static ref L1_GAS: Felt252 = Felt252::from_hex(
480+
"0x00000000000000000000000000000000000000000000000000004c315f474153"
481+
)
482+
.unwrap();
483+
static ref L2_GAS: Felt252 = Felt252::from_hex(
484+
"0x00000000000000000000000000000000000000000000000000004c325f474153"
485+
)
486+
.unwrap();
487+
}
488+
489+
let mut resource_bounds = vec![];
490+
let mut tip = 0;
491+
let mut paymaster_data = vec![];
492+
let mut nonce_data_availability_mode: u32 = 0;
493+
let mut fee_data_availability_mode: u32 = 0;
494+
let mut account_deployment_data = vec![];
495+
if let VersionSpecificAccountTxFields::Current(fields) =
496+
&self.tx_execution_context.account_tx_fields
497+
{
498+
resource_bounds.push(ResourceBounds {
499+
resource: *L1_GAS,
500+
max_amount: fields.l1_resource_bounds.max_amount,
501+
max_price_per_unit: fields.l1_resource_bounds.max_price_per_unit,
502+
});
503+
if let Some(bounds) = &fields.l2_resource_bounds {
504+
resource_bounds.push(ResourceBounds {
505+
resource: *L2_GAS,
506+
max_amount: bounds.max_amount,
507+
max_price_per_unit: bounds.max_price_per_unit,
508+
});
509+
}
510+
tip = fields.tip as u128;
511+
paymaster_data = fields.paymaster_data.clone();
512+
account_deployment_data = fields.account_deployment_data.clone();
513+
nonce_data_availability_mode = fields.nonce_data_availability_mode.into();
514+
fee_data_availability_mode = fields.fee_data_availability_mode.into();
515+
}
516+
517+
Ok(ExecutionInfoV2 {
518+
block_info: BlockInfo {
519+
block_number: self.block_context.block_info.block_number,
520+
block_timestamp: self.block_context.block_info.block_timestamp,
521+
sequencer_address: self.block_context.block_info.sequencer_address.0,
522+
},
523+
tx_info: TxV2Info {
524+
version: self.tx_execution_context.version,
525+
account_contract_address: self.tx_execution_context.account_contract_address.0,
526+
max_fee: self
527+
.tx_execution_context
528+
.account_tx_fields
529+
.max_fee_for_execution_info(),
530+
signature: self.tx_execution_context.signature.clone(),
531+
transaction_hash: self.tx_execution_context.transaction_hash,
532+
chain_id: self.block_context.starknet_os_config.chain_id,
533+
nonce: self.tx_execution_context.nonce,
534+
resource_bounds,
535+
tip,
536+
paymaster_data,
537+
nonce_data_availability_mode,
538+
fee_data_availability_mode,
539+
account_deployment_data,
540+
},
541+
caller_address: self.caller_address.0,
542+
contract_address: self.contract_address.0,
543+
entry_point_selector: self.entry_point_selector,
544+
})
471545
}
472546

473547
fn secp256k1_add(

src/transaction/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,15 @@ impl From<starknet_api::data_availability::DataAvailabilityMode> for DataAvailab
332332
}
333333
}
334334

335+
impl From<DataAvailabilityMode> for Felt252 {
336+
fn from(val: DataAvailabilityMode) -> Self {
337+
match val {
338+
DataAvailabilityMode::L1 => Felt252::ZERO,
339+
DataAvailabilityMode::L2 => Felt252::ONE,
340+
}
341+
}
342+
}
343+
335344
impl From<DataAvailabilityMode> for u64 {
336345
fn from(val: DataAvailabilityMode) -> Self {
337346
match val {
@@ -341,6 +350,15 @@ impl From<DataAvailabilityMode> for u64 {
341350
}
342351
}
343352

353+
impl From<DataAvailabilityMode> for u32 {
354+
fn from(val: DataAvailabilityMode) -> Self {
355+
match val {
356+
DataAvailabilityMode::L1 => 0,
357+
DataAvailabilityMode::L2 => 1,
358+
}
359+
}
360+
}
361+
344362
#[derive(Clone, Debug, Default)]
345363
pub struct ResourceBounds {
346364
pub max_amount: u64,
@@ -395,6 +413,13 @@ impl VersionSpecificAccountTxFields {
395413
}
396414
}
397415

416+
pub(crate) fn max_fee_for_execution_info(&self) -> u128 {
417+
match self {
418+
Self::Deprecated(max_fee) => *max_fee,
419+
Self::Current(_) => 0,
420+
}
421+
}
422+
398423
pub fn fee_type(&self) -> FeeType {
399424
match self {
400425
Self::Deprecated(_) => FeeType::Eth,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use core::starknet::contract_address::ContractAddress;
2+
3+
#[starknet::interface]
4+
trait IGetExecutionInfo<TContractState> {
5+
fn get_info(self: @TContractState) -> (ContractAddress, ContractAddress, ContractAddress, ContractAddress);
6+
}
7+
8+
#[starknet::contract]
9+
mod GetExecutionInfo {
10+
use starknet::info::get_execution_info;
11+
use starknet::info::v2::ExecutionInfo;
12+
use core::starknet::contract_address::ContractAddress;
13+
use box::BoxTrait;
14+
use array::SpanTrait;
15+
16+
#[storage]
17+
struct Storage {
18+
}
19+
20+
#[external(v0)]
21+
impl GetExecutionInfo of super::IGetExecutionInfo<ContractState> {
22+
fn get_info(self: @ContractState) -> (ContractAddress, ContractAddress, ContractAddress, ContractAddress) {
23+
let info = get_execution_info().unbox();
24+
let block_info = info.block_info.unbox();
25+
let tx_info = info.tx_info.unbox();
26+
27+
let block_number = block_info.block_number;
28+
let block_timestamp = block_info.block_timestamp;
29+
let sequencer_address = block_info.sequencer_address;
30+
31+
let version = tx_info.version;
32+
let account_contract_address = tx_info.account_contract_address;
33+
let max_fee = tx_info.max_fee;
34+
let signature = tx_info.signature;
35+
let transaction_hash = tx_info.transaction_hash;
36+
let chain_id = tx_info.chain_id;
37+
let nonce = tx_info.nonce;
38+
39+
let caller_address = info.caller_address;
40+
let contract_address = info.contract_address;
41+
let entry_point_selector = info.entry_point_selector;
42+
43+
// V2 fields
44+
45+
let resource_bounds = tx_info.resource_bounds;
46+
let tip = tx_info.tip;
47+
let paymaster_data = tx_info.paymaster_data;
48+
let nonce_da_mode = tx_info.nonce_data_availability_mode;
49+
let fee_da_mode = tx_info.fee_data_availability_mode;
50+
let account_deployment_data = tx_info.account_deployment_data;
51+
52+
assert(block_number == 0, 'Wrong Block Number');
53+
assert(block_timestamp == 0, 'Wrong Block Timestamp');
54+
assert(version == 1, 'Wrong Version');
55+
assert(max_fee == 0, 'Wrong max fee');
56+
assert(transaction_hash == 0, 'Wrong Tx Hash');
57+
assert(chain_id == 1536727068981429685321, 'Wrong Chain Id');
58+
assert(nonce == 10, 'Wrong Nonce');
59+
assert(entry_point_selector == 1583979555264088613757654119588925070177786702073426169970015447448454297318, 'Wrong Entrypoint Selector');
60+
assert(*signature.at(0) == 22, 'Wrong Signature');
61+
assert(*signature.at(1) == 33, 'Wrong Signature');
62+
assert(signature.len() == 2, 'Wrong Signature len');
63+
assert(*resource_bounds.at(0).resource == 83774935613779, 'Wrong L1 gas resource name');
64+
assert(*resource_bounds.at(0).max_amount == 30, 'Wrong L1 gas max amount');
65+
assert(*resource_bounds.at(0).max_price_per_unit == 15, 'Wrong L1 gas max price per unit');
66+
assert(*resource_bounds.at(1).resource== 83779230581075, 'Wrong L1 gas resource name');
67+
assert(*resource_bounds.at(1).max_amount == 10, 'Wrong L2 gas max amount');
68+
assert(*resource_bounds.at(1).max_price_per_unit == 5, 'Wrong L2 gas max price per unit');
69+
assert(tip == 3, 'Wrong Tip');
70+
assert(*paymaster_data.at(0) == 6, 'Wrong Paymaster Data');
71+
assert(*paymaster_data.at(1) == 17, 'Wrong Paymaster Data');
72+
assert(paymaster_data.len() == 2, 'Wrong Paymaster Data len');
73+
assert(nonce_da_mode == 0, 'Wrong Nonce DA Mode');
74+
assert(fee_da_mode == 1, 'Wrong Fee DA Mode');
75+
assert(*account_deployment_data.at(0) == 7, 'Wrong Acc. Deployment Data');
76+
assert(*account_deployment_data.at(1) == 18, 'Wrong Acc. Deployment Data');
77+
assert(account_deployment_data.len() == 2, 'Wrong Acc. Deployment Data len');
78+
79+
return (
80+
sequencer_address,
81+
account_contract_address,
82+
caller_address,
83+
contract_address
84+
);
85+
}
86+
}
87+
}

starknet_programs/cairo2/math_lib.cairo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[starnet::interface]
1+
#[starknet::interface]
22
trait IMath<TContractState> {
33
fn square_root(ref self: TContractState, n: felt252) -> felt252;
44
}

0 commit comments

Comments
 (0)