Skip to content

Commit

Permalink
feat: Pragma ExEx (#6)
Browse files Browse the repository at this point in the history
* feat(pragma_exex): Pragma ExEx

* feat(pragma_exex): Enough context now
!

* feat(pragma_exex): CHANGELOG

* feat(pragma_exex): Pragma ExEx

* feat(pragma_exex):  available in ExExContext

* feat(pragma_exex): Cleaning

* feat(pragma_exex): Cleaning

* feat(pragma_exex): Cleaned ExEx

* feat(pragma_exex): Devnet config

* feat(pragma_exex): Max fee

* feat(pragma_exex): Renaming

* feat(pragma_exex): get feeds from contract!

* feat(pragma_exex): Smarter!

* feat(pragma_exex):

* feat(pragma_exex): logs

* feat(pragma_exex): Logs

* feat(pragma_exex): Interval constant

* feat(pragma_exex): Status & receipt

* feat(pragma_exex):

* feat(pragma_exex): Clean
  • Loading branch information
akhercha authored Oct 2, 2024
1 parent 1284dc2 commit b2cdbfc
Show file tree
Hide file tree
Showing 55 changed files with 656 additions and 384 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- feat: `exex_pragma_dispatch` implementation
- feat: Madara ExExs proof of concept
- fix(docs): updated readme and fixed launcher
- fix(ci): added gateway key to fix rate limit on tests
Expand Down
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"crates/primitives/chain_config",
"crates/primitives/utils",
"crates/primitives/exex",
"crates/primitives/rpc_provider",
"crates/proc-macros",
"crates/tests",
]
Expand All @@ -45,6 +46,7 @@ default-members = [
"crates/primitives/chain_config",
"crates/primitives/utils",
"crates/primitives/exex",
"crates/primitives/rpc_provider",
"crates/proc-macros",
"crates/tests",
]
Expand Down Expand Up @@ -95,6 +97,7 @@ mp-state-update = { path = "crates/primitives/state_update", default-features =
mp-utils = { path = "crates/primitives/utils", default-features = false }
mp-chain-config = { path = "crates/primitives/chain_config", default-features = false }
mp-exex = { path = "crates/primitives/exex", default-features = false }
mp-rpc = { path = "crates/primitives/rpc_provider", default-features = false }

# Madara client
mc-telemetry = { path = "crates/client/telemetry" }
Expand Down
2 changes: 1 addition & 1 deletion configs/presets/devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ versioned_constants:
eth_core_contract_address: "0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057"
latest_protocol_version: "0.13.2"
block_time: "1s"
pending_block_update_time: "500ms"
pending_block_update_time: "100ms"
execution_batch_size: 16
bouncer_config:
block_max_capacity:
Expand Down
1 change: 1 addition & 0 deletions crates/client/exec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mp-block = { workspace = true }
mp-chain-config = { workspace = true }
mp-class = { workspace = true }
mp-convert = { workspace = true }
mp-rpc = { workspace = true }

# Starknet
blockifier = { workspace = true }
Expand Down
22 changes: 22 additions & 0 deletions crates/client/exec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use blockifier::{
},
};
use mc_db::{db_block_id::DbBlockId, MadaraStorageError};
use mp_rpc::errors::StarknetRpcApiError;
use starknet_api::transaction::TransactionHash;
use starknet_types_core::felt::Felt;

Expand Down Expand Up @@ -39,6 +40,27 @@ pub enum Error {
InvalidSequencerAddress(Felt),
}

impl From<Error> for StarknetRpcApiError {
fn from(val: Error) -> Self {
match val {
Error::UnsupportedProtocolVersion(_) => {
StarknetRpcApiError::ErrUnexpectedError { data: "Unsupported protocol version".to_string() }
}
Error::Reexecution(_) => StarknetRpcApiError::TxnExecutionError {
tx_index: 0,
error: "Transaction reexecution error".to_string(),
},
Error::FeeEstimation(_) => StarknetRpcApiError::InsufficientMaxFee,
Error::MessageFeeEstimation(_) => StarknetRpcApiError::InsufficientMaxFee,
Error::CallContract(_) => StarknetRpcApiError::ContractError,
Error::Storage(_) => StarknetRpcApiError::ErrUnexpectedError { data: "Storage error".to_string() },
Error::InvalidSequencerAddress(_) => {
StarknetRpcApiError::ErrUnexpectedError { data: "Invalid sequencer address".to_string() }
}
}
}
}

#[derive(thiserror::Error, Debug)]
#[error("Reexecuting tx {hash:#} (index {index}) on top of {block_n}: {err:#}")]
pub struct TxReexecError {
Expand Down
1 change: 1 addition & 0 deletions crates/client/mempool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mp-class.workspace = true
mp-convert.workspace = true
mp-exex.workspace = true
mp-receipt.workspace = true
mp-rpc.workspace = true
mp-state-update.workspace = true
mp-transactions.workspace = true
mp-utils.workspace = true
Expand Down
12 changes: 7 additions & 5 deletions crates/client/mempool/src/block_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> {
// This is compute heavy as it does the commitments and trie computations.
let import_result = close_block(
&self.importer,
block_to_close,
block_to_close.clone(),
&new_state_diff,
self.backend.chain_config().chain_id.clone(),
block_n,
Expand All @@ -432,7 +432,7 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> {
self.current_pending_tick = 0;

log::info!("⛏️ Closed block #{} with {} transactions - {:?}", block_n, n_txs, start_time.elapsed());
let _ = self.notify_exexs(block_n).context("Sending notification to ExExs");
let _ = self.notify_exexs(block_to_close, block_n).context("Sending notification to ExExs");

Ok(())
}
Expand Down Expand Up @@ -487,12 +487,14 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> {
}

/// Sends a notification to the ExExs that a block has been closed.
fn notify_exexs(&self, block_n: u64) -> anyhow::Result<()> {
fn notify_exexs(&self, block_produced: MadaraPendingBlock, block_number: u64) -> anyhow::Result<()> {
let Some(manager) = self.exex_manager.as_ref() else {
return Ok(());
};

let notification = ExExNotification::BlockClosed { new: BlockNumber(block_n) };
let notification = ExExNotification::BlockProduced {
block: Box::new(block_produced),
block_number: BlockNumber(block_number),
};
manager.send(notification).map_err(|e| anyhow::anyhow!("Could not send ExEx notification: {}", e))
}
}
18 changes: 18 additions & 0 deletions crates/client/mempool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use mp_block::BlockId;
use mp_block::BlockTag;
use mp_block::MadaraPendingBlockInfo;
use mp_class::ConvertedClass;
use mp_rpc::errors::StarknetRpcApiError;
use mp_transactions::broadcasted_to_blockifier;
use mp_transactions::BroadcastedToBlockifierError;
use starknet_api::core::{ContractAddress, Nonce};
Expand Down Expand Up @@ -60,6 +61,23 @@ impl Error {
}
}

impl From<Error> for StarknetRpcApiError {
fn from(val: Error) -> Self {
match val {
Error::InnerMempool(TxInsersionError::NonceConflict) => StarknetRpcApiError::DuplicateTxn,
Error::Validation(err) => StarknetRpcApiError::ValidationFailure { error: format!("{err:#}") },
Error::InnerMempool(err) => StarknetRpcApiError::ValidationFailure { error: format!("{err:#}") },
Error::Exec(err) => StarknetRpcApiError::TxnExecutionError { tx_index: 0, error: format!("{err:#}") },
Error::StorageError(err) => {
StarknetRpcApiError::ErrUnexpectedError { data: format!("Storage error: {err:#}") }
}
Error::BroadcastedToBlockifier(err) => {
StarknetRpcApiError::ErrUnexpectedError { data: format!("Preprocessing transaction: {err:#}") }
}
}
}
}

#[cfg_attr(test, mockall::automock)]
pub trait MempoolProvider: Send + Sync {
fn accept_invoke_tx(&self, tx: BroadcastedInvokeTransaction) -> Result<InvokeTransactionResult, Error>;
Expand Down
1 change: 1 addition & 0 deletions crates/client/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mp-chain-config = { workspace = true }
mp-class = { workspace = true }
mp-convert = { workspace = true, default-features = true }
mp-receipt = { workspace = true }
mp-rpc = { workspace = true }
mp-state-update = { workspace = true }
mp-transactions = { workspace = true }
mp-utils = { workspace = true }
Expand Down
79 changes: 1 addition & 78 deletions crates/client/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//! It uses the madara client and backend in order to answer queries.

mod constants;
mod errors;
mod macros;
pub mod providers;
#[cfg(test)]
Expand All @@ -13,84 +12,8 @@ pub mod utils;
pub mod versions;

use jsonrpsee::RpcModule;
use starknet_types_core::felt::Felt;
use std::sync::Arc;

use mc_db::db_block_id::DbBlockIdResolvable;
use mc_db::MadaraBackend;
use mp_block::{MadaraMaybePendingBlock, MadaraMaybePendingBlockInfo};
use mp_chain_config::{ChainConfig, RpcVersion};
use mp_convert::ToFelt;

use errors::{StarknetRpcApiError, StarknetRpcResult};
use providers::AddTransactionProvider;
use utils::ResultExt;

/// A Starknet RPC server for Madara
#[derive(Clone)]
pub struct Starknet {
backend: Arc<MadaraBackend>,
chain_config: Arc<ChainConfig>,
pub(crate) add_transaction_provider: Arc<dyn AddTransactionProvider>,
}

impl Starknet {
pub fn new(
backend: Arc<MadaraBackend>,
chain_config: Arc<ChainConfig>,
add_transaction_provider: Arc<dyn AddTransactionProvider>,
) -> Self {
Self { backend, add_transaction_provider, chain_config }
}

pub fn clone_backend(&self) -> Arc<MadaraBackend> {
Arc::clone(&self.backend)
}

pub fn get_block_info(
&self,
block_id: &impl DbBlockIdResolvable,
) -> StarknetRpcResult<MadaraMaybePendingBlockInfo> {
self.backend
.get_block_info(block_id)
.or_internal_server_error("Error getting block from storage")?
.ok_or(StarknetRpcApiError::BlockNotFound)
}

pub fn get_block_n(&self, block_id: &impl DbBlockIdResolvable) -> StarknetRpcResult<u64> {
self.backend
.get_block_n(block_id)
.or_internal_server_error("Error getting block from storage")?
.ok_or(StarknetRpcApiError::BlockNotFound)
}

pub fn get_block(&self, block_id: &impl DbBlockIdResolvable) -> StarknetRpcResult<MadaraMaybePendingBlock> {
self.backend
.get_block(block_id)
.or_internal_server_error("Error getting block from storage")?
.ok_or(StarknetRpcApiError::BlockNotFound)
}

pub fn chain_id(&self) -> Felt {
self.chain_config.chain_id.clone().to_felt()
}

pub fn current_block_number(&self) -> StarknetRpcResult<u64> {
self.get_block_n(&mp_block::BlockId::Tag(mp_block::BlockTag::Latest))
}

pub fn current_spec_version(&self) -> RpcVersion {
RpcVersion::RPC_VERSION_LATEST
}

pub fn get_l1_last_confirmed_block(&self) -> StarknetRpcResult<u64> {
Ok(self
.backend
.get_l1_last_confirmed_block()
.or_internal_server_error("Error getting L1 last confirmed block")?
.unwrap_or_default())
}
}
use mp_rpc::Starknet;

/// Returns the RpcModule merged with all the supported RPC versions.
pub fn versioned_rpc_api(starknet: &Starknet, read: bool, write: bool, trace: bool) -> anyhow::Result<RpcModule<()>> {
Expand Down
5 changes: 2 additions & 3 deletions crates/client/rpc/src/providers/forward_to_provider.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use jsonrpsee::core::{async_trait, RpcResult};
use mp_rpc::{errors::StarknetRpcApiError, AddTransactionProvider};
use starknet_core::types::{
BroadcastedDeclareTransaction, BroadcastedDeployAccountTransaction, BroadcastedInvokeTransaction,
DeclareTransactionResult, DeployAccountTransactionResult, InvokeTransactionResult,
};
use starknet_providers::{Provider, ProviderError};

use crate::{bail_internal_server_error, errors::StarknetRpcApiError};

use super::AddTransactionProvider;
use mp_rpc::bail_internal_server_error;

pub struct ForwardToProvider<P: Provider + Send + Sync> {
provider: P,
Expand Down
Loading

0 comments on commit b2cdbfc

Please sign in to comment.