Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: starkware-libs/sequencer
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a24e9fd2f0dc13f57e428e29ba98abdb20e8b472
Choose a base ref
..
head repository: starkware-libs/sequencer
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8c8184d1772cf6a62c2a633c654eead22e5410d0
Choose a head ref
1 change: 1 addition & 0 deletions Cargo.lock

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

50 changes: 50 additions & 0 deletions config/mempool/default_config.json
Original file line number Diff line number Diff line change
@@ -54,6 +54,51 @@
"privacy": "Public",
"value": 3
},
"components.consensus_manager.component_type": {
"description": "The component type.",
"privacy": "Public",
"value": "AsynchronousComponent"
},
"components.consensus_manager.execute": {
"description": "The component execution flag.",
"privacy": "Public",
"value": true
},
"components.consensus_manager.local_config.#is_none": {
"description": "Flag for an optional field.",
"privacy": "TemporaryValue",
"value": false
},
"components.consensus_manager.local_config.channel_buffer_size": {
"description": "The communication channel buffer size.",
"privacy": "Public",
"value": 32
},
"components.consensus_manager.location": {
"description": "The component location.",
"privacy": "Public",
"value": "Local"
},
"components.consensus_manager.remote_config.#is_none": {
"description": "Flag for an optional field.",
"privacy": "TemporaryValue",
"value": true
},
"components.consensus_manager.remote_config.ip": {
"description": "The remote component server ip.",
"privacy": "Public",
"value": "0.0.0.0"
},
"components.consensus_manager.remote_config.port": {
"description": "The remote component server port.",
"privacy": "Public",
"value": 8080
},
"components.consensus_manager.remote_config.retries": {
"description": "The max number of retries for sending a message.",
"privacy": "Public",
"value": 3
},
"components.gateway.component_type": {
"description": "The component type.",
"privacy": "Public",
@@ -144,6 +189,11 @@
"privacy": "Public",
"value": 3
},
"consensus_manager_config.consensus_config_param_1": {
"description": "The first consensus manager configuration parameter",
"privacy": "Public",
"value": 1
},
"gateway_config.network_config.ip": {
"description": "The gateway server ip.",
"privacy": "Public",
14 changes: 12 additions & 2 deletions crates/mempool/src/mempool.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;

use starknet_api::core::{ContractAddress, Nonce};
use starknet_api::executable_transaction::Transaction;
use starknet_api::transaction::{Tip, TransactionHash};
use starknet_mempool_types::errors::MempoolError;
use starknet_mempool_types::mempool_types::{
@@ -68,7 +69,7 @@ impl Mempool {
let mut eligible_txs: Vec<ThinTransaction> = Vec::with_capacity(n_txs);
for tx_ref in &eligible_tx_references {
let tx = self.tx_pool.remove(tx_ref.tx_hash)?;
eligible_txs.push(tx);
eligible_txs.push((&tx).into());
}

// Update the mempool state with the given transactions' nonces.
@@ -137,7 +138,7 @@ impl Mempool {
// Remove transactions with lower nonce than the account nonce.
self.tx_pool.remove_up_to_nonce(sender_address, nonce);

self.tx_pool.insert(tx)?;
self.tx_pool.insert((&tx).into())?;

// Maybe close nonce gap.
if self.tx_queue.get_nonce(sender_address).is_none() {
@@ -232,4 +233,13 @@ impl TransactionReference {
tip: tx.tip,
}
}

pub fn new(tx: &Transaction) -> Self {
TransactionReference {
sender_address: tx.contract_address(),
nonce: tx.nonce(),
tx_hash: tx.tx_hash(),
tip: tx.tip().expect("Expected a valid tip value, but received None."),
}
}
}
2 changes: 1 addition & 1 deletion crates/mempool/src/mempool_test.rs
Original file line number Diff line number Diff line change
@@ -114,7 +114,7 @@ impl FromIterator<ThinTransaction> for TransactionPool {
fn from_iter<T: IntoIterator<Item = ThinTransaction>>(txs: T) -> Self {
let mut pool = Self::default();
for tx in txs {
pool.insert(tx).unwrap();
pool.insert((&tx).into()).unwrap();
}
pool
}
32 changes: 13 additions & 19 deletions crates/mempool/src/transaction_pool.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use std::collections::{hash_map, BTreeMap, HashMap};

use starknet_api::core::{ContractAddress, Nonce};
use starknet_api::executable_transaction::Transaction;
use starknet_api::transaction::TransactionHash;
use starknet_mempool_types::errors::MempoolError;
use starknet_mempool_types::mempool_types::{
Account,
AccountState,
MempoolResult,
ThinTransaction,
};
use starknet_mempool_types::mempool_types::{Account, AccountState, MempoolResult};

use crate::mempool::TransactionReference;

type HashToTransaction = HashMap<TransactionHash, ThinTransaction>;
type HashToTransaction = HashMap<TransactionHash, Transaction>;

/// Contains all transactions currently held in the mempool.
/// Invariant: both data structures are consistent regarding the existence of transactions:
@@ -27,8 +23,8 @@ pub struct TransactionPool {
}

impl TransactionPool {
pub fn insert(&mut self, tx: ThinTransaction) -> MempoolResult<()> {
let tx_reference = TransactionReference::new_from_thin_tx(&tx);
pub fn insert(&mut self, tx: Transaction) -> MempoolResult<()> {
let tx_reference = TransactionReference::new(&tx);
let tx_hash = tx_reference.tx_hash;

// Insert to pool.
@@ -50,20 +46,18 @@ impl TransactionPool {
Ok(())
}

pub fn remove(&mut self, tx_hash: TransactionHash) -> MempoolResult<ThinTransaction> {
pub fn remove(&mut self, tx_hash: TransactionHash) -> MempoolResult<Transaction> {
// Remove from pool.
let tx =
self.tx_pool.remove(&tx_hash).ok_or(MempoolError::TransactionNotFound { tx_hash })?;

// Remove from account mapping.
self.txs_by_account.remove(TransactionReference::new_from_thin_tx(&tx)).unwrap_or_else(
|| {
panic!(
"Transaction pool consistency error: transaction with hash {tx_hash} appears \
in main mapping, but does not appear in the account mapping"
)
},
);
self.txs_by_account.remove(TransactionReference::new(&tx)).unwrap_or_else(|| {
panic!(
"Transaction pool consistency error: transaction with hash {tx_hash} appears in \
main mapping, but does not appear in the account mapping"
)
});

Ok(tx)
}
@@ -81,7 +75,7 @@ impl TransactionPool {
}
}

pub fn _get_by_tx_hash(&self, tx_hash: TransactionHash) -> MempoolResult<&ThinTransaction> {
pub fn _get_by_tx_hash(&self, tx_hash: TransactionHash) -> MempoolResult<&Transaction> {
self.tx_pool.get(&tx_hash).ok_or(MempoolError::TransactionNotFound { tx_hash })
}

Original file line number Diff line number Diff line change
@@ -12,6 +12,59 @@ use serde::Serialize;
use super::definitions::{ClientError, ClientResult};
use crate::component_definitions::APPLICATION_OCTET_STREAM;

/// The `RemoteComponentClient` struct is a generic client for sending component requests and
/// receiving responses asynchronously through HTTP connection.
///
/// # Type Parameters
/// - `Request`: The type of the request. This type must implement the `serde::Serialize` trait.
/// - `Response`: The type of the response. This type must implement the
/// `serde::de::DeserializeOwned` (e.g. by using #[derive(Deserialize)]) trait.
///
/// # Fields
/// - `uri`: URI address of the server.
/// - `client`: The inner HTTP client that initiates the connection to the server and manages it.
/// - `max_retries`: Configurable number of extra attempts to send a request to server in case of a
/// failure.
///
/// # Example
/// ```rust
/// // Example usage of the RemoteComponentClient
///
/// use serde::{Deserialize, Serialize};
///
/// use crate::starknet_mempool_infra::component_client::RemoteComponentClient;
///
/// // Define your request and response types
/// #[derive(Serialize)]
/// struct MyRequest {
/// pub content: String,
/// }
///
/// #[derive(Deserialize)]
/// struct MyResponse {
/// content: String,
/// }
///
/// #[tokio::main]
/// async fn main() {
/// // Create a channel for sending requests and receiving responses
/// // Instantiate the client.
/// let ip_address = std::net::IpAddr::V6(std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
/// let port: u16 = 8080;
/// let client = RemoteComponentClient::<MyRequest, MyResponse>::new(ip_address, port, 2);
///
/// // Instantiate a request.
/// let request = MyRequest { content: "Hello, world!".to_string() };
///
/// // Send the request; typically, the client should await for a response.
/// client.send(request);
/// }
/// ```
///
/// # Notes
/// - The `RemoteComponentClient` struct is designed to work in an asynchronous environment,
/// utilizing Tokio's async runtime and hyper framwork to send HTTP requests and receive HTTP
/// responses.
pub struct RemoteComponentClient<Request, Response>
where
Request: Serialize,
Original file line number Diff line number Diff line change
@@ -19,6 +19,89 @@ use crate::component_definitions::{
APPLICATION_OCTET_STREAM,
};

/// The `RemoteComponentServer` struct is a generic server that handles requests and responses for a
/// specified component. It receives requests, processes them using the provided component, and
/// sends back responses. The server needs to be started using the `start` function, which runs
/// indefinitely.
///
/// # Type Parameters
///
/// - `Component`: The type of the component that will handle the requests. This type must implement
/// the `ComponentRequestHandler` trait, which defines how the component processes requests and
/// generates responses.
/// - `Request`: The type of requests that the component will handle. This type must implement the
/// `serde::de::DeserializeOwned` (e.g. by using #[derive(Deserialize)]) trait.
/// - `Response`: The type of responses that the component will generate. This type must implement
/// the `Serialize` trait.
///
/// # Fields
///
/// - `component`: The component responsible for handling the requests and generating responses.
/// - `socket`: A socket address for the server to listen on.
///
/// # Example
/// ```rust
/// // Example usage of the RemoteComponentServer
/// use async_trait::async_trait;
/// use serde::{Deserialize, Serialize};
/// use starknet_mempool_infra::component_runner::{ComponentStartError, ComponentStarter};
/// use tokio::task;
///
/// use crate::starknet_mempool_infra::component_definitions::ComponentRequestHandler;
/// use crate::starknet_mempool_infra::component_server::{
/// ComponentServerStarter,
/// RemoteComponentServer,
/// };
///
/// // Define your component
/// struct MyComponent {}
///
/// #[async_trait]
/// impl ComponentStarter for MyComponent {
/// async fn start(&mut self) -> Result<(), ComponentStartError> {
/// Ok(())
/// }
/// }
///
/// // Define your request and response types
/// #[derive(Deserialize)]
/// struct MyRequest {
/// pub content: String,
/// }
///
/// #[derive(Serialize)]
/// struct MyResponse {
/// pub content: String,
/// }
///
/// // Define your request processing logic
/// #[async_trait]
/// impl ComponentRequestHandler<MyRequest, MyResponse> for MyComponent {
/// async fn handle_request(&mut self, request: MyRequest) -> MyResponse {
/// MyResponse { content: request.content.clone() + " processed" }
/// }
/// }
///
/// #[tokio::main]
/// async fn main() {
/// // Instantiate the component.
/// let component = MyComponent {};
///
/// // Set the ip address and port of the server's socket.
/// let ip_address = std::net::IpAddr::V6(std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
/// let port: u16 = 8080;
///
/// // Instantiate the server.
/// let mut server = RemoteComponentServer::<MyComponent, MyRequest, MyResponse>::new(
/// component, ip_address, port,
/// );
///
/// // Start the server in a new task.
/// task::spawn(async move {
/// server.start().await;
/// });
/// }
/// ```
pub struct RemoteComponentServer<Component, Request, Response>
where
Component: ComponentRequestHandler<Request, Response> + Send + 'static,
1 change: 1 addition & 0 deletions crates/mempool_node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ rstest.workspace = true
serde.workspace = true
starknet_batcher.workspace = true
starknet_batcher_types.workspace = true
starknet_consensus_manager.workspace = true
starknet_gateway.workspace = true
starknet_mempool.workspace = true
starknet_mempool_infra.workspace = true
16 changes: 13 additions & 3 deletions crates/mempool_node/src/config/config_test.rs
Original file line number Diff line number Diff line change
@@ -124,6 +124,10 @@ fn test_invalid_components_config() {
// Initialize an invalid config and check that the validator finds an error.
let component_config = ComponentConfig {
batcher: ComponentExecutionConfig { execute: false, ..ComponentExecutionConfig::default() },
consensus_manager: ComponentExecutionConfig {
execute: false,
..ComponentExecutionConfig::default()
},
gateway: ComponentExecutionConfig { execute: false, ..ComponentExecutionConfig::default() },
mempool: ComponentExecutionConfig { execute: false, ..ComponentExecutionConfig::default() },
};
@@ -138,11 +142,13 @@ fn test_invalid_components_config() {
/// Test the validation of the struct ComponentConfig.
/// The validation validates at least one of the components is set with execute: true.
#[rstest]
#[case(true, false, false)]
#[case(false, true, false)]
#[case(false, false, true)]
#[case(true, false, false, false)]
#[case(false, true, false, false)]
#[case(false, false, true, false)]
#[case(false, false, false, true)]
fn test_valid_components_config(
#[case] batcher_component_execute: bool,
#[case] consensus_manager_component_execute: bool,
#[case] gateway_component_execute: bool,
#[case] mempool_component_execute: bool,
) {
@@ -152,6 +158,10 @@ fn test_valid_components_config(
execute: batcher_component_execute,
..ComponentExecutionConfig::default()
},
consensus_manager: ComponentExecutionConfig {
execute: consensus_manager_component_execute,
..ComponentExecutionConfig::default()
},
gateway: ComponentExecutionConfig {
execute: gateway_component_execute,
..ComponentExecutionConfig::default()
Loading