Skip to content

Commit

Permalink
feat(blockifier): add get_execution_info_v1 syscall (#1735)
Browse files Browse the repository at this point in the history
  • Loading branch information
varex83 authored Nov 14, 2024
1 parent 875cd27 commit 564ad89
Show file tree
Hide file tree
Showing 9 changed files with 1,074 additions and 15 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#[starknet::contract]
mod TestContract {
use box::BoxTrait;
use starknet::ClassHash;
use starknet::ContractAddress;
use starknet::syscalls::get_execution_info_syscall;
use starknet::info::ExecutionInfo;
use starknet::info::BlockInfo;
use starknet::info::TxInfo;
use starknet::{SyscallResultTrait, SyscallResult};

#[storage]
struct Storage {}

#[external(v0)]
fn test_get_execution_info(
self: @ContractState,
expected_block_number: u64,
expected_block_timestamp: u64,
expected_sequencer_address: ContractAddress,
expected_tx_info: TxInfo,
expected_caller_address: felt252,
expected_contract_address: felt252,
expected_entry_point_selector: felt252,
) {
let execution_info = get_execution_info_syscall().unwrap_syscall().unbox();
let block_info = execution_info.block_info.unbox();

assert(block_info.block_number == expected_block_number, 'BLOCK_NUMBER_MISMATCH');
assert(block_info.block_timestamp == expected_block_timestamp, 'BLOCK_TIMESTAMP_MISMATCH');
assert(
block_info.sequencer_address.into() == expected_sequencer_address, 'SEQUENCER_MISMATCH',
);

let tx_info = execution_info.tx_info.unbox();
assert(tx_info.version == expected_tx_info.version, 'TX_INFO_VERSION_MISMATCH');
assert(
tx_info.account_contract_address.into() == expected_tx_info.account_contract_address,
'ACCOUNT_C_ADDRESS_MISMATCH',
);
assert(tx_info.max_fee == expected_tx_info.max_fee, 'TX_INFO_MAX_FEE_MISMATCH');
assert(tx_info.signature == expected_tx_info.signature, 'TX_INFO_SIGNATURE_MISMATCH');
assert(
tx_info.transaction_hash == expected_tx_info.transaction_hash, 'TX_INFO_HASH_MISMATCH',
);
assert(tx_info.chain_id == expected_tx_info.chain_id, 'TX_INFO_CHAIN_ID_MISMATCH');
assert(tx_info.nonce == expected_tx_info.nonce, 'TX_INFO_NONCE_MISMATCH');

assert(execution_info.caller_address.into() == expected_caller_address, 'CALLER_MISMATCH');
assert(
execution_info.contract_address.into() == expected_contract_address, 'CONTRACT_MISMATCH'
);
assert(
execution_info.entry_point_selector == expected_entry_point_selector,
'SELECTOR_MISMATCH'
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ use crate::execution::errors::{ConstructorEntryPointExecutionError, EntryPointEx
use crate::execution::execution_utils::{
felt_from_ptr,
felt_range_from_ptr,
max_fee_for_execution_info,
ReadOnlySegment,
ReadOnlySegments,
};
Expand Down Expand Up @@ -389,7 +388,7 @@ impl<'a> DeprecatedSyscallHintProcessor<'a> {
let tx_info: Vec<MaybeRelocatable> = vec![
tx_info.signed_version().0.into(),
(*tx_info.sender_address().0.key()).into(),
max_fee_for_execution_info(tx_info).into(),
Felt::from(tx_info.max_fee_for_execution_info_syscall().0).into(),
tx_signature_length.into(),
tx_signature_start_ptr.into(),
tx_info.transaction_hash().0.into(),
Expand Down
9 changes: 0 additions & 9 deletions crates/blockifier/src/execution/execution_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ use crate::execution::stack_trace::extract_trailing_cairo1_revert_trace;
use crate::execution::{deprecated_entry_point_execution, entry_point_execution};
use crate::state::errors::StateError;
use crate::state::state_api::State;
use crate::transaction::objects::TransactionInfo;

pub type Args = Vec<CairoArg>;

Expand Down Expand Up @@ -361,14 +360,6 @@ pub fn write_maybe_relocatable<T: Into<MaybeRelocatable>>(
Ok(())
}

pub fn max_fee_for_execution_info(tx_info: &TransactionInfo) -> Felt {
match tx_info {
TransactionInfo::Current(_) => 0,
TransactionInfo::Deprecated(tx_info) => tx_info.max_fee.0,
}
.into()
}

/// Returns the VM resources required for running `poseidon_hash_many` in the Starknet OS.
pub fn poseidon_hash_many_cost(data_length: usize) -> ExecutionResources {
ExecutionResources {
Expand Down
63 changes: 61 additions & 2 deletions crates/blockifier/src/execution/native/syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use std::collections::HashSet;
use std::hash::RandomState;

use cairo_native::starknet::{
BlockInfo,
ExecutionInfo,
ExecutionInfoV2,
Secp256k1Point,
Secp256r1Point,
StarknetSyscallHandler,
SyscallResult,
TxInfo,
U256,
};
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
Expand All @@ -23,6 +25,7 @@ use crate::execution::call_info::{
OrderedL2ToL1Message,
Retdata,
};
use crate::execution::common_hints::ExecutionMode;
use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionContext};
use crate::execution::errors::EntryPointExecutionError;
use crate::execution::syscalls::hint_processor::{
Expand Down Expand Up @@ -161,6 +164,51 @@ impl<'state> NativeSyscallHandler<'state> {
}
}
}

fn get_tx_info_v1(&self) -> TxInfo {
let tx_info = &self.context.tx_context.tx_info;
TxInfo {
version: tx_info.version().0,
account_contract_address: Felt::from(tx_info.sender_address()),
max_fee: tx_info.max_fee_for_execution_info_syscall().0,
signature: tx_info.signature().0,
transaction_hash: tx_info.transaction_hash().0,
chain_id: Felt::from_hex(
&self.context.tx_context.block_context.chain_info.chain_id.as_hex(),
)
.expect("Failed to convert the chain_id to hex."),
nonce: tx_info.nonce().0,
}
}

fn get_block_info(&self) -> BlockInfo {
let block_info = &self.context.tx_context.block_context.block_info;
if self.context.execution_mode == ExecutionMode::Validate {
let versioned_constants = self.context.versioned_constants();
let block_number = block_info.block_number.0;
let block_timestamp = block_info.block_timestamp.0;
// Round down to the nearest multiple of validate_block_number_rounding.
let validate_block_number_rounding =
versioned_constants.get_validate_block_number_rounding();
let rounded_block_number =
(block_number / validate_block_number_rounding) * validate_block_number_rounding;
// Round down to the nearest multiple of validate_timestamp_rounding.
let validate_timestamp_rounding = versioned_constants.get_validate_timestamp_rounding();
let rounded_timestamp =
(block_timestamp / validate_timestamp_rounding) * validate_timestamp_rounding;
BlockInfo {
block_number: rounded_block_number,
block_timestamp: rounded_timestamp,
sequencer_address: Felt::ZERO,
}
} else {
BlockInfo {
block_number: block_info.block_number.0,
block_timestamp: block_info.block_timestamp.0,
sequencer_address: Felt::from(block_info.sequencer_address),
}
}
}
}

impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {
Expand All @@ -172,8 +220,19 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {
todo!("Implement get_block_hash syscall.");
}

fn get_execution_info(&mut self, _remaining_gas: &mut u128) -> SyscallResult<ExecutionInfo> {
todo!("Implement get_execution_info syscall.");
fn get_execution_info(&mut self, remaining_gas: &mut u128) -> SyscallResult<ExecutionInfo> {
self.pre_execute_syscall(
remaining_gas,
self.context.gas_costs().get_execution_info_gas_cost,
)?;

Ok(ExecutionInfo {
block_info: self.get_block_info(),
tx_info: self.get_tx_info_v1(),
caller_address: Felt::from(self.call.caller_address),
contract_address: Felt::from(self.call.storage_address),
entry_point_selector: self.call.entry_point_selector.0,
})
}

fn get_execution_info_v2(
Expand Down
3 changes: 1 addition & 2 deletions crates/blockifier/src/execution/syscalls/hint_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use crate::execution::errors::{ConstructorEntryPointExecutionError, EntryPointEx
use crate::execution::execution_utils::{
felt_from_ptr,
felt_range_from_ptr,
max_fee_for_execution_info,
write_maybe_relocatable,
ReadOnlySegment,
ReadOnlySegments,
Expand Down Expand Up @@ -638,7 +637,7 @@ impl<'a> SyscallHintProcessor<'a> {
let mut tx_data: Vec<MaybeRelocatable> = vec![
tx_info.signed_version().0.into(),
tx_info.sender_address().0.key().into(),
max_fee_for_execution_info(tx_info).into(),
Felt::from(tx_info.max_fee_for_execution_info_syscall().0).into(),
tx_signature_start_ptr.into(),
tx_signature_end_ptr.into(),
(tx_info).transaction_hash().0.into(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ use crate::transaction::objects::{
TransactionInfo,
};

#[cfg_attr(
feature = "cairo_native",
test_case(
FeatureContract::SierraExecutionInfoV1Contract,
ExecutionMode::Validate,
TransactionVersion::ONE,
false;
"Native [V1]: Validate execution mode: block info fields should be zeroed. Transaction V1."
)
)]
#[cfg_attr(
feature = "cairo_native",
test_case(
FeatureContract::SierraExecutionInfoV1Contract,
ExecutionMode::Execute,
TransactionVersion::ONE,
false;
"Native [V1]: Execute execution mode: block info should be as usual. Transaction V1."
)
)]
#[test_case(
FeatureContract::TestContract(CairoVersion::Cairo1),
ExecutionMode::Validate,
Expand Down Expand Up @@ -121,6 +141,10 @@ fn test_get_execution_info(
};
vec![]
}
#[cfg(feature = "cairo_native")]
FeatureContract::SierraExecutionInfoV1Contract => {
vec![]
}
_ => {
vec![
Felt::ZERO, // Tip.
Expand Down Expand Up @@ -148,6 +172,8 @@ fn test_get_execution_info(

let expected_resource_bounds: Vec<Felt> = match (test_contract, version) {
(FeatureContract::LegacyTestContract, _) => vec![],
#[cfg(feature = "cairo_native")]
(FeatureContract::SierraExecutionInfoV1Contract, _) => vec![],
(_, version) if version == TransactionVersion::ONE => vec![
felt!(0_u16), // Length of resource bounds array.
],
Expand Down
20 changes: 20 additions & 0 deletions crates/blockifier/src/test_utils/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const SECURITY_TEST_CONTRACT_BASE: u32 = 6 * CLASS_HASH_BASE;
const TEST_CONTRACT_BASE: u32 = 7 * CLASS_HASH_BASE;
const ERC20_CONTRACT_BASE: u32 = 8 * CLASS_HASH_BASE;
const CAIRO_STEPS_TEST_CONTRACT_BASE: u32 = 9 * CLASS_HASH_BASE;
#[cfg(feature = "cairo_native")]
const SIERRA_EXECUTION_INFO_V1_CONTRACT_BASE: u32 = 10 * CLASS_HASH_BASE;

// Contract names.
const ACCOUNT_LONG_VALIDATE_NAME: &str = "account_with_long_validate";
Expand All @@ -65,6 +67,8 @@ const LEGACY_CONTRACT_NAME: &str = "legacy_test_contract";
const SECURITY_TEST_CONTRACT_NAME: &str = "security_tests_contract";
const TEST_CONTRACT_NAME: &str = "test_contract";
const CAIRO_STEPS_TEST_CONTRACT_NAME: &str = "cairo_steps_test_contract";
#[cfg(feature = "cairo_native")]
const EXECUTION_INFO_V1_CONTRACT_NAME: &str = "test_contract_execution_info_v1";

// ERC20 contract is in a unique location.
const ERC20_CAIRO0_CONTRACT_SOURCE_PATH: &str =
Expand Down Expand Up @@ -95,6 +99,8 @@ pub enum FeatureContract {
SecurityTests,
TestContract(CairoVersion),
CairoStepsTestContract,
#[cfg(feature = "cairo_native")]
SierraExecutionInfoV1Contract,
}

impl FeatureContract {
Expand All @@ -108,6 +114,8 @@ impl FeatureContract {
| Self::ERC20(version) => *version,
Self::SecurityTests => CairoVersion::Cairo0,
Self::LegacyTestContract | Self::CairoStepsTestContract => CairoVersion::Cairo1,
#[cfg(feature = "cairo_native")]
Self::SierraExecutionInfoV1Contract => CairoVersion::Native,
}
}

Expand All @@ -119,6 +127,8 @@ impl FeatureContract {
| Self::FaultyAccount(_)
| Self::TestContract(_)
| Self::ERC20(_) => true,
#[cfg(feature = "cairo_native")]
Self::SierraExecutionInfoV1Contract => false,
Self::SecurityTests | Self::LegacyTestContract | Self::CairoStepsTestContract => false,
}
}
Expand All @@ -134,6 +144,10 @@ impl FeatureContract {
Self::LegacyTestContract | Self::SecurityTests | Self::CairoStepsTestContract => {
panic!("{self:?} contract has no configurable version.")
}
#[cfg(feature = "cairo_native")]
Self::SierraExecutionInfoV1Contract => {
panic!("{self:?} contract has no configurable version.")
}
}
}

Expand Down Expand Up @@ -224,6 +238,8 @@ impl FeatureContract {
Self::SecurityTests => SECURITY_TEST_CONTRACT_BASE,
Self::TestContract(_) => TEST_CONTRACT_BASE,
Self::CairoStepsTestContract => CAIRO_STEPS_TEST_CONTRACT_BASE,
#[cfg(feature = "cairo_native")]
Self::SierraExecutionInfoV1Contract => SIERRA_EXECUTION_INFO_V1_CONTRACT_BASE,
}
}

Expand All @@ -237,6 +253,8 @@ impl FeatureContract {
Self::SecurityTests => SECURITY_TEST_CONTRACT_NAME,
Self::TestContract(_) => TEST_CONTRACT_NAME,
Self::CairoStepsTestContract => CAIRO_STEPS_TEST_CONTRACT_NAME,
#[cfg(feature = "cairo_native")]
Self::SierraExecutionInfoV1Contract => EXECUTION_INFO_V1_CONTRACT_NAME,
Self::ERC20(_) => unreachable!(),
}
}
Expand Down Expand Up @@ -314,6 +332,8 @@ impl FeatureContract {
| FeatureContract::TestContract(_)
| FeatureContract::LegacyTestContract
| FeatureContract::CairoStepsTestContract => None,
#[cfg(feature = "cairo_native")]
FeatureContract::SierraExecutionInfoV1Contract => None,
FeatureContract::ERC20(_) => unreachable!(),
};
cairo0_compile(self.get_source_path(), extra_arg, false)
Expand Down
7 changes: 7 additions & 0 deletions crates/blockifier/src/transaction/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ impl TransactionInfo {
TransactionInfo::Deprecated(_) => GasVectorComputationMode::NoL2Gas,
}
}

pub fn max_fee_for_execution_info_syscall(&self) -> Fee {
match self {
Self::Current(_) => Fee(0),
Self::Deprecated(context) => context.max_fee,
}
}
}

impl HasRelatedFeeType for TransactionInfo {
Expand Down

0 comments on commit 564ad89

Please sign in to comment.