Add mempool stub (#29)
* add mempool stub * address review comments * move base data types to nomos-core * allow clippy warning
This commit is contained in:
parent
fb3fd6f3b1
commit
539c986f69
|
@ -5,5 +5,6 @@ members = [
|
||||||
"nomos-services/log",
|
"nomos-services/log",
|
||||||
"nomos-services/network",
|
"nomos-services/network",
|
||||||
"nomos-services/storage",
|
"nomos-services/storage",
|
||||||
"nomos-services/consensus"
|
"nomos-services/consensus",
|
||||||
|
"nomos-services/mempool"
|
||||||
]
|
]
|
|
@ -1,7 +1,15 @@
|
||||||
/// A block
|
/// A block
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Block;
|
pub struct Block;
|
||||||
|
|
||||||
|
/// A block header
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct BlockHeader;
|
||||||
|
|
||||||
|
/// Identifier of a block
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct BlockId;
|
||||||
|
|
||||||
/// A block chunk, N pieces are necessary to reconstruct the full block
|
/// A block chunk, N pieces are necessary to reconstruct the full block
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct BlockChunk {
|
pub struct BlockChunk {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "mempool"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait = "0.1"
|
||||||
|
overwatch-rs = { git = "https://github.com/logos-co/Overwatch", branch = "main" }
|
||||||
|
nomos-network = { path = "../network", features = ["waku"] }
|
||||||
|
nomos-core = { path = "../../nomos-core" }
|
||||||
|
tracing = "0.1"
|
||||||
|
tokio = { version = "1", features = ["sync"] }
|
||||||
|
futures = "0.3"
|
|
@ -0,0 +1,26 @@
|
||||||
|
use nomos_core::block::{BlockHeader, BlockId};
|
||||||
|
|
||||||
|
pub trait Pool {
|
||||||
|
type Tx;
|
||||||
|
type Id;
|
||||||
|
|
||||||
|
/// Construct a new empty pool
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
|
/// Add a new transaction to the mempool, for example because we received it from the network
|
||||||
|
fn add_tx(&mut self, tx: Self::Tx, id: Self::Id) -> Result<(), overwatch_rs::DynError>;
|
||||||
|
|
||||||
|
/// Return a view over the transactions contained in the mempool.
|
||||||
|
/// Implementations should provide *at least* all the transactions which have not been marked as
|
||||||
|
/// in a block.
|
||||||
|
/// The hint on the ancestor *can* be used by the implementation to display additional
|
||||||
|
/// transactions that were not included up to that point if available.
|
||||||
|
fn view(&self, ancestor_hint: BlockId) -> Box<dyn Iterator<Item = Self::Tx> + Send>;
|
||||||
|
|
||||||
|
/// Record that a set of transactions were included in a block
|
||||||
|
fn mark_in_block(&mut self, txs: Vec<Self::Id>, block: BlockHeader);
|
||||||
|
|
||||||
|
/// Signal that a set of transactions can't be possibly requested anymore and can be
|
||||||
|
/// discarded.
|
||||||
|
fn prune(&mut self, txs: Vec<Self::Id>);
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
/// std
|
||||||
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
|
|
||||||
|
/// crates
|
||||||
|
use tokio::sync::broadcast::Receiver;
|
||||||
|
use tokio::sync::oneshot::Sender;
|
||||||
|
|
||||||
|
/// internal
|
||||||
|
pub mod backend;
|
||||||
|
use backend::Pool;
|
||||||
|
use nomos_core::block::{BlockHeader, BlockId};
|
||||||
|
use nomos_network::{
|
||||||
|
backends::{waku::NetworkEvent, NetworkBackend},
|
||||||
|
NetworkService,
|
||||||
|
};
|
||||||
|
use overwatch_rs::services::{
|
||||||
|
handle::ServiceStateHandle,
|
||||||
|
relay::{OutboundRelay, Relay, RelayMessage},
|
||||||
|
state::{NoOperator, NoState},
|
||||||
|
ServiceCore, ServiceData, ServiceId,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Mempool<
|
||||||
|
N: NetworkBackend + Send + Sync + 'static,
|
||||||
|
Tx: Debug + Send + Sync + 'static,
|
||||||
|
Id: Debug + Send + Sync + 'static,
|
||||||
|
P: Pool<Tx = Tx, Id = Id> + Send + Sync + 'static,
|
||||||
|
> {
|
||||||
|
service_state: ServiceStateHandle<Self>,
|
||||||
|
network_relay: Relay<NetworkService<N>>,
|
||||||
|
pool: P,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MempoolMsg<Tx, Id> {
|
||||||
|
AddTx {
|
||||||
|
id: Id,
|
||||||
|
tx: Tx,
|
||||||
|
},
|
||||||
|
View {
|
||||||
|
ancestor_hint: BlockId,
|
||||||
|
rx: Sender<Box<dyn Iterator<Item = Tx> + Send>>,
|
||||||
|
},
|
||||||
|
Prune {
|
||||||
|
ids: Vec<Id>,
|
||||||
|
},
|
||||||
|
MarkInBlock {
|
||||||
|
ids: Vec<Id>,
|
||||||
|
block: BlockHeader,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Tx: Debug, Id: Debug> Debug for MempoolMsg<Tx, Id> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
Self::View { ancestor_hint, .. } => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"MempoolMsg::View {{ ancestor_hint: {:?}}}",
|
||||||
|
ancestor_hint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Self::AddTx { id, tx } => write!(f, "MempoolMsg::AddTx{{id: {:?}, tx: {:?}}}", id, tx),
|
||||||
|
Self::Prune { ids } => write!(f, "MempoolMsg::Prune{{ids: {:?}}}", ids),
|
||||||
|
Self::MarkInBlock { ids, block } => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"MempoolMsg::MarkInBlock{{ids: {:?}, block: {:?}}}",
|
||||||
|
ids, block
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Tx: 'static, Id: 'static> RelayMessage for MempoolMsg<Tx, Id> {}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
N: NetworkBackend + Send + Sync + 'static,
|
||||||
|
Tx: Debug + Send + Sync + 'static,
|
||||||
|
Id: Debug + Send + Sync + 'static,
|
||||||
|
P: Pool<Tx = Tx, Id = Id> + Send + Sync + 'static,
|
||||||
|
> ServiceData for Mempool<N, Tx, Id, P>
|
||||||
|
{
|
||||||
|
const SERVICE_ID: ServiceId = "Mempool";
|
||||||
|
type Settings = ();
|
||||||
|
type State = NoState<Self::Settings>;
|
||||||
|
type StateOperator = NoOperator<Self::State>;
|
||||||
|
type Message = MempoolMsg<Tx, Id>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<N, Tx, Id, P> ServiceCore for Mempool<N, Tx, Id, P>
|
||||||
|
where
|
||||||
|
Tx: Debug + Send + Sync + 'static,
|
||||||
|
Id: Debug + Send + Sync + 'static,
|
||||||
|
P: Pool<Tx = Tx, Id = Id> + Send + Sync + 'static,
|
||||||
|
N: NetworkBackend + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
fn init(service_state: ServiceStateHandle<Self>) -> Result<Self, overwatch_rs::DynError> {
|
||||||
|
let network_relay = service_state.overwatch_handle.relay();
|
||||||
|
Ok(Self {
|
||||||
|
service_state,
|
||||||
|
network_relay,
|
||||||
|
pool: P::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
|
||||||
|
async fn run(mut self) -> Result<(), overwatch_rs::DynError> {
|
||||||
|
let Self {
|
||||||
|
service_state,
|
||||||
|
network_relay,
|
||||||
|
pool,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let network_relay: OutboundRelay<_> = network_relay
|
||||||
|
.connect()
|
||||||
|
.await
|
||||||
|
.expect("Relay connection with NetworkService should succeed");
|
||||||
|
|
||||||
|
// Separate function so that we can specialize it for different network backends
|
||||||
|
let network_txs: Receiver<NetworkEvent> = todo!();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
Some(msg) = service_state.inbound_relay.recv() => {
|
||||||
|
match msg {
|
||||||
|
MempoolMsg::AddTx { id, tx } => {
|
||||||
|
pool.add_tx(tx, id).unwrap_or_else(|e| {
|
||||||
|
tracing::debug!("could not add tx to the pool due to: {}", e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
MempoolMsg::View { ancestor_hint, rx } => {
|
||||||
|
rx.send(pool.view(ancestor_hint)).unwrap_or_else(|_| {
|
||||||
|
tracing::debug!("could not send back pool view")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
MempoolMsg::MarkInBlock { ids, block } => {
|
||||||
|
pool.mark_in_block(ids, block);
|
||||||
|
}
|
||||||
|
MempoolMsg::Prune { ids } => pool.prune(ids),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg) = network_txs.recv() => {
|
||||||
|
// filter incoming transactions and add them to the pool
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue