-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
exex.rs
92 lines (86 loc) · 3.23 KB
/
exex.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#![allow(dead_code)]
// todo: expand this (examples, assumptions, invariants)
//! Execution extensions (ExEx).
//!
//! An execution extension is a task that derives its state from Reth's state.
//!
//! Some examples of state such state derives are rollups, bridges, and indexers.
//!
//! An ExEx is a [`Future`] resolving to a `Result<()>` that is run indefinitely alongside Reth.
//!
//! ExEx's are initialized using an async closure that resolves to the ExEx; this closure gets
//! passed an [`ExExContext`] where it is possible to spawn additional tasks and modify Reth.
//!
//! Most ExEx's will want to derive their state from the [`CanonStateNotification`] channel given in
//! [`ExExContext`]. A new notification is emitted whenever blocks are executed in live and
//! historical sync.
//!
//! # Pruning
//!
//! ExEx's **SHOULD** emit an `ExExEvent::FinishedHeight` event to signify what blocks have been
//! processed. This event is used by Reth to determine what state can be pruned.
//!
//! An ExEx will not receive notifications for blocks less than the block emitted in the event. To
//! clarify: if the ExEx emits `ExExEvent::FinishedHeight(0)` it will receive notifications for any
//! `block_number >= 0`.
//!
//! [`Future`]: std::future::Future
//! [`ExExContext`]: reth_exex::ExExContext
//! [`CanonStateNotification`]: reth_provider::CanonStateNotification
use crate::FullNodeTypes;
use futures::{future::BoxFuture, FutureExt};
use reth_exex::ExExContext;
use std::future::Future;
/// A trait for launching an ExEx.
trait LaunchExEx<Node: FullNodeTypes>: Send {
/// Launches the ExEx.
///
/// The ExEx should be able to run independently and emit events on the channels provided in
/// the [`ExExContext`].
fn launch(
self,
ctx: ExExContext<Node>,
) -> impl Future<Output = eyre::Result<impl Future<Output = eyre::Result<()>> + Send>> + Send;
}
type BoxExEx = BoxFuture<'static, eyre::Result<()>>;
/// A version of [LaunchExEx] that returns a boxed future. Makes the trait object-safe.
pub(crate) trait BoxedLaunchExEx<Node: FullNodeTypes>: Send {
fn launch(self: Box<Self>, ctx: ExExContext<Node>)
-> BoxFuture<'static, eyre::Result<BoxExEx>>;
}
/// Implements [BoxedLaunchExEx] for any [LaunchExEx] that is [Send] and `'static`.
///
/// Returns a [BoxFuture] that resolves to a [BoxExEx].
impl<E, Node> BoxedLaunchExEx<Node> for E
where
E: LaunchExEx<Node> + Send + 'static,
Node: FullNodeTypes,
{
fn launch(
self: Box<Self>,
ctx: ExExContext<Node>,
) -> BoxFuture<'static, eyre::Result<BoxExEx>> {
async move {
let exex = LaunchExEx::launch(*self, ctx).await?;
Ok(Box::pin(exex) as BoxExEx)
}
.boxed()
}
}
/// Implements `LaunchExEx` for any closure that takes an [ExExContext] and returns a future
/// resolving to an ExEx.
impl<Node, F, Fut, E> LaunchExEx<Node> for F
where
Node: FullNodeTypes,
F: FnOnce(ExExContext<Node>) -> Fut + Send,
Fut: Future<Output = eyre::Result<E>> + Send,
E: Future<Output = eyre::Result<()>> + Send,
{
fn launch(
self,
ctx: ExExContext<Node>,
) -> impl Future<Output = eyre::Result<impl Future<Output = eyre::Result<()>> + Send>> + Send
{
self(ctx)
}
}