cuprate_dandelion_tower/lib.rs
1//! # Dandelion Tower
2//!
3//! This crate implements [dandelion++](https://arxiv.org/pdf/1805.11060.pdf), using [`tower`].
4//!
5//! This crate provides 2 [`tower::Service`]s, a [`DandelionRouter`] and a [`DandelionPoolManager`](pool::DandelionPoolManager).
6//! The router is pretty minimal and only handles the absolute necessary data to route transactions, whereas the
7//! pool keeps track of all data necessary for dandelion++ but requires you to provide a backing tx-pool.
8//!
9//! This split was done not because the [`DandelionPoolManager`](pool::DandelionPoolManager) is unnecessary but because it is hard
10//! to cover a wide range of projects when abstracting over the tx-pool. Not using the [`DandelionPoolManager`](pool::DandelionPoolManager)
11//! requires you to implement part of the paper yourself.
12//!
13//! # Features
14//!
15//! This crate only has one feature `txpool` which enables [`DandelionPoolManager`](pool::DandelionPoolManager).
16//!
17//! # Needed Services
18//!
19//! To use this crate you need to provide a few types.
20//!
21//! ## Diffuse Service
22//!
23//! This service should implement diffusion, which is sending the transaction to every peer, with each peer
24//! having a timer using the exponential distribution and batch sending all txs that were queued in that time.
25//!
26//! The diffuse service should have a request of [`DiffuseRequest`](traits::DiffuseRequest) and it's error
27//! should be [`tower::BoxError`].
28//!
29//! ## Outbound Peer `TryStream`
30//!
31//! The outbound peer [`TryStream`](futures::TryStream) should provide a stream of randomly selected outbound
32//! peers, these peers will then be used to route stem txs to.
33//!
34//! The peers will not be returned anywhere, so it is recommended to wrap them in some sort of drop guard that returns
35//! them back to a peer set.
36//!
37//! ## Peer Service
38//!
39//! This service represents a connection to an individual peer, this should be returned from the Outbound Peer
40//! `TryStream`. This should immediately send the transaction to the peer when requested, it should _not_ set
41//! a timer.
42//!
43//! The peer service should have a request of [`StemRequest`](traits::StemRequest) and its error
44//! should be [`tower::BoxError`].
45//!
46//! ## Backing Pool
47//!
48//! ([`DandelionPoolManager`](pool::DandelionPoolManager) only)
49//!
50//! This service is a backing tx-pool, in memory or on disk.
51//! The backing pool should have a request of [`TxStoreRequest`](traits::TxStoreRequest) and a response of
52//! [`TxStoreResponse`](traits::TxStoreResponse), with an error of [`tower::BoxError`].
53//!
54//! Users should keep a handle to the backing pool to request data from it, when requesting data you _must_
55//! make sure you only look in the public pool if you are going to be giving data to peers, as stem transactions
56//! must stay private.
57//!
58//! When removing data, for example because of a new block, you can remove from both pools provided it doesn't leak
59//! any data about stem transactions. You will probably want to set up a task that monitors the tx pool for stuck transactions,
60//! transactions that slipped in just as one was removed etc, this crate does not handle that.
61mod config;
62#[cfg(feature = "txpool")]
63pub mod pool;
64mod router;
65#[cfg(test)]
66mod tests;
67pub mod traits;
68
69pub use config::*;
70pub use router::*;