This repository has been archived by the owner on Aug 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 291
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
237019d
commit 709857a
Showing
2 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
[package] | ||
name = "pallet-starknet-runtime-api" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
# Madara primitives | ||
mp-block = { workspace = true } | ||
mp-chain-id = { workspace = true } | ||
mp-commitments = { workspace = true } | ||
mp-digest-log = { workspace = true } | ||
mp-fee = { workspace = true } | ||
mp-felt = { workspace = true, features = ["parity-scale-codec", "serde"] } | ||
mp-hashers = { workspace = true } | ||
mp-sequencer-address = { workspace = true, features = ["parity-scale-codec"] } | ||
mp-state = { workspace = true } | ||
mp-storage = { workspace = true, features = ["parity-scale-codec"] } | ||
mp-transactions = { workspace = true, features = ["scale-info"] } | ||
|
||
blockifier = { workspace = true, features = [ | ||
"testing", | ||
"parity-scale-codec", | ||
"scale-info", | ||
] } | ||
starknet-core = { workspace = true } | ||
starknet-crypto = { workspace = true, features = ["alloc"] } | ||
starknet_api = { workspace = true, features = [ | ||
"scale-info", | ||
"parity-scale-codec", | ||
] } | ||
|
||
# Substrate frame | ||
frame-benchmarking = { workspace = true, optional = true } | ||
frame-support = { workspace = true } | ||
frame-system = { workspace = true } | ||
# Substrate Client | ||
sc-cli = { workspace = true, optional = true } | ||
# Substrate primitives | ||
sp-api = { workspace = true } | ||
sp-arithmetic = { workspace = true } | ||
sp-core = { workspace = true } | ||
sp-inherents = { workspace = true } | ||
sp-io = { workspace = true } | ||
sp-runtime = { workspace = true } | ||
sp-std = { workspace = true } | ||
# Frame pallets | ||
|
||
# Other third party dependencies | ||
cairo-lang-casm-contract-class = { workspace = true, optional = true, features = [ | ||
"std", | ||
] } | ||
derive_more = { workspace = true } | ||
hashbrown = { workspace = true } | ||
hex = { workspace = true } | ||
indexmap = { workspace = true } | ||
log = { workspace = true } | ||
parity-scale-codec = { workspace = true, features = ["derive"] } | ||
reqwest = { workspace = true, optional = true, features = [ | ||
"blocking", | ||
"rustls-tls", | ||
] } | ||
scale-info = { workspace = true, features = ["derive"] } | ||
serde = { workspace = true, features = ["derive"] } | ||
serde_json = { workspace = true } | ||
serde_with = { workspace = true } | ||
|
||
[dev-dependencies] | ||
pallet-timestamp = { workspace = true } | ||
pretty_assertions = { workspace = true } | ||
test-case = "3.1.0" | ||
lazy_static = "1.4.0" | ||
hexlit = "0.5.5" | ||
assert_matches = "1.5.0" | ||
starknet-ff = { workspace = true } | ||
project-root = "0.2.2" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
# Substrate | ||
"frame-support/std", | ||
"frame-system/std", | ||
"sc-cli", | ||
"sp-io/std", | ||
"sp-runtime/std", | ||
"frame-benchmarking?/std", | ||
"scale-info/std", | ||
"pallet-timestamp/std", | ||
"sp-inherents/std", | ||
# Starknet | ||
"starknet-crypto/std", | ||
"blockifier/std", | ||
"mp-sequencer-address/std", | ||
"mp-felt/std", | ||
# Other third party dependencies | ||
"dep:reqwest", | ||
"dep:cairo-lang-casm-contract-class", | ||
"parity-scale-codec/std", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//! Definition of the runtime API for the StarkNet pallet. | ||
// Adding allow unused type parameters to avoid clippy errors | ||
// generated by the `decl_runtime_apis` macro. | ||
// Specifically, the macro generates a trait (`StarknetRuntimeApi`) with unused type parameters. | ||
#![allow(clippy::extra_unused_type_parameters)] | ||
|
||
use alloc::sync::Arc; | ||
|
||
use blockifier::execution::contract_class::ContractClass; | ||
use mp_felt::Felt252Wrapper; | ||
use mp_transactions::{Transaction, TxType, UserTransaction}; | ||
use sp_api::BlockT; | ||
pub extern crate alloc; | ||
use alloc::string::String; | ||
use alloc::vec::Vec; | ||
|
||
use sp_runtime::DispatchError; | ||
use starknet_api::api_core::{ChainId, ClassHash, ContractAddress, EntryPointSelector, Nonce}; | ||
use starknet_api::block::{BlockNumber, BlockTimestamp}; | ||
use starknet_api::hash::StarkFelt; | ||
use starknet_api::state::StorageKey; | ||
use starknet_api::transaction::{Calldata, Event as StarknetEvent, TransactionHash}; | ||
|
||
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, scale_info::TypeInfo)] | ||
pub enum StarknetTransactionExecutionError { | ||
ContractNotFound, | ||
ClassAlreadyDeclared, | ||
ClassHashNotFound, | ||
InvalidContractClass, | ||
ContractError, | ||
} | ||
|
||
sp_api::decl_runtime_apis! { | ||
pub trait StarknetRuntimeApi { | ||
/// Returns the nonce associated with the given address in the given block | ||
fn nonce(contract_address: ContractAddress) -> Nonce; | ||
/// Returns a storage slot value | ||
fn get_storage_at(address: ContractAddress, key: StorageKey) -> Result<StarkFelt, DispatchError>; | ||
/// Returns a `Call` response. | ||
fn call(address: ContractAddress, function_selector: EntryPointSelector, calldata: Calldata) -> Result<Vec<Felt252Wrapper>, DispatchError>; | ||
/// Returns the contract class hash at the given address. | ||
fn contract_class_hash_by_address(address: ContractAddress) -> ClassHash; | ||
/// Returns the contract class for the given class hash. | ||
fn contract_class_by_class_hash(class_hash: ClassHash) -> Option<ContractClass>; | ||
/// Returns the chain id. | ||
fn chain_id() -> Felt252Wrapper; | ||
/// Returns fee estimate | ||
fn estimate_fee(transactions: Vec<UserTransaction>) -> Result<Vec<(u64, u64)>, DispatchError>; | ||
/// Filters extrinsic transactions to return only Starknet transactions | ||
/// | ||
/// To support runtime upgrades, the client must be unaware of the specific extrinsic | ||
/// details. To achieve this, the client uses an OpaqueExtrinsic type to represent and | ||
/// manipulate extrinsics. However, the client cannot decode and filter extrinsics due to | ||
/// this limitation. The solution is to offload decoding and filtering to the RuntimeApi in | ||
/// the runtime itself, accomplished through the extrinsic_filter method. This enables the | ||
/// client to operate seamlessly while abstracting the extrinsic complexity. | ||
fn extrinsic_filter(xts: Vec<<Block as BlockT>::Extrinsic>) -> Vec<Transaction>; | ||
fn get_events_for_tx_hash(xts: Vec<<Block as BlockT>::Extrinsic>, chain_id: Felt252Wrapper, tx_hash: Felt252Wrapper) -> Option<(TxType, Vec<StarknetEvent>)>; | ||
|
||
/// Return the list of StarknetEvent evmitted during this block, along with the hash of the starknet transaction they bellong to | ||
/// | ||
/// `block_extrinsics` is the list of all the extrinsic executed during this block, it is used in order to match | ||
fn get_starknet_events_and_their_associated_tx_hash(block_extrinsics: Vec<<Block as BlockT>::Extrinsic>, chain_id: Felt252Wrapper) -> Vec<(Felt252Wrapper, StarknetEvent)>; | ||
/// Return the outcome of the tx execution | ||
fn get_tx_execution_outcome(tx_hash: TransactionHash) -> Option<Vec<u8>>; | ||
/// Return the block context | ||
fn get_block_context() -> BlockContext; | ||
} | ||
|
||
pub trait ConvertTransactionRuntimeApi { | ||
/// Converts the transaction to an UncheckedExtrinsic for submission to the pool. | ||
fn convert_transaction(transaction: UserTransaction) -> Result<<Block as BlockT>::Extrinsic, DispatchError>; | ||
/// Converts the DispatchError to an understandable error for the client | ||
fn convert_error(error: DispatchError) -> StarknetTransactionExecutionError; | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, parity_scale_codec::Encode, parity_scale_codec::Decode, scale_info::TypeInfo)] | ||
pub struct BlockContext { | ||
pub chain_id: String, | ||
pub block_number: u64, | ||
pub block_timestamp: u64, | ||
|
||
// Fee-related. | ||
pub sequencer_address: ContractAddress, | ||
pub fee_token_address: ContractAddress, | ||
pub vm_resource_fee_cost: Vec<(String, sp_arithmetic::fixed_point::FixedU128)>, | ||
pub gas_price: u128, // In wei. | ||
|
||
// Limits. | ||
pub invoke_tx_max_n_steps: u32, | ||
pub validate_max_n_steps: u32, | ||
pub max_recursion_depth: u32, | ||
} | ||
|
||
#[cfg(feature = "std")] | ||
use std::collections::HashMap; | ||
|
||
#[cfg(not(feature = "std"))] | ||
use hashbrown::HashMap; | ||
|
||
impl From<BlockContext> for blockifier::block_context::BlockContext { | ||
fn from(value: BlockContext) -> Self { | ||
Self { | ||
chain_id: ChainId(value.chain_id), | ||
block_number: BlockNumber(value.block_number), | ||
block_timestamp: BlockTimestamp(value.block_timestamp), | ||
sequencer_address: value.sequencer_address, | ||
fee_token_address: value.fee_token_address, | ||
vm_resource_fee_cost: Arc::new(HashMap::from_iter(value.vm_resource_fee_cost)), | ||
gas_price: value.gas_price, | ||
invoke_tx_max_n_steps: value.invoke_tx_max_n_steps, | ||
validate_max_n_steps: value.validate_max_n_steps, | ||
max_recursion_depth: value.max_recursion_depth, | ||
} | ||
} | ||
} | ||
|
||
impl From<blockifier::block_context::BlockContext> for BlockContext { | ||
fn from(value: blockifier::block_context::BlockContext) -> Self { | ||
Self { | ||
chain_id: value.chain_id.0, | ||
block_number: value.block_number.0, | ||
block_timestamp: value.block_timestamp.0, | ||
sequencer_address: value.sequencer_address, | ||
fee_token_address: value.fee_token_address, | ||
vm_resource_fee_cost: Vec::from_iter(value.vm_resource_fee_cost.iter().map(|(k, v)| (k.clone(), *v))), | ||
gas_price: value.gas_price, | ||
invoke_tx_max_n_steps: value.invoke_tx_max_n_steps, | ||
validate_max_n_steps: value.validate_max_n_steps, | ||
max_recursion_depth: value.max_recursion_depth, | ||
} | ||
} | ||
} |