|
| 1 | +use async_trait::async_trait; |
| 2 | +use jsonrpsee::{ |
| 3 | + core::RpcResult, |
| 4 | + proc_macros::rpc, |
| 5 | + types::{error, ErrorObjectOwned}, |
| 6 | +}; |
| 7 | +use reth_network_api::FullNetwork; |
| 8 | +use reth_scroll_node::ScrollNetworkPrimitives; |
| 9 | +use rollup_node_manager::RollupManagerHandle; |
| 10 | +use tokio::sync::{oneshot, Mutex, OnceCell}; |
| 11 | + |
| 12 | +/// RPC extension for rollup node management operations. |
| 13 | +/// |
| 14 | +/// This struct provides a custom JSON-RPC namespace (`rollupNode`) that exposes |
| 15 | +/// rollup management functionality to RPC clients. It manages a connection to the |
| 16 | +/// rollup manager through a handle that is initialized lazily via a oneshot channel. |
| 17 | +#[derive(Debug)] |
| 18 | +pub struct RollupNodeRpcExt<N> |
| 19 | +where |
| 20 | + N: FullNetwork<Primitives = ScrollNetworkPrimitives>, |
| 21 | +{ |
| 22 | + /// Cached rollup manager handle, initialized lazily via `OnceCell` |
| 23 | + handle: tokio::sync::OnceCell<RollupManagerHandle<N>>, |
| 24 | + /// Oneshot channel receiver for obtaining the rollup manager handle during initialization |
| 25 | + rx: Mutex<Option<oneshot::Receiver<RollupManagerHandle<N>>>>, |
| 26 | +} |
| 27 | + |
| 28 | +impl<N> RollupNodeRpcExt<N> |
| 29 | +where |
| 30 | + N: FullNetwork<Primitives = ScrollNetworkPrimitives>, |
| 31 | +{ |
| 32 | + /// Creates a new RPC extension with a receiver for the rollup manager handle. |
| 33 | + pub fn new(rx: oneshot::Receiver<RollupManagerHandle<N>>) -> Self { |
| 34 | + Self { rx: Mutex::new(Some(rx)), handle: OnceCell::new() } |
| 35 | + } |
| 36 | + |
| 37 | + /// Gets or initializes the rollup manager handle. |
| 38 | + /// |
| 39 | + /// This method lazily initializes the rollup manager handle by consuming the oneshot |
| 40 | + /// receiver. Subsequent calls will return the cached handle. |
| 41 | + async fn rollup_manager_handle(&self) -> eyre::Result<&RollupManagerHandle<N>> { |
| 42 | + self.handle |
| 43 | + .get_or_try_init(|| async { |
| 44 | + let rx = { |
| 45 | + let mut g = self.rx.lock().await; |
| 46 | + g.take().ok_or_else(|| eyre::eyre!("receiver already consumed"))? |
| 47 | + }; |
| 48 | + rx.await.map_err(|e| eyre::eyre!("failed to receive handle: {e}")) |
| 49 | + }) |
| 50 | + .await |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +/// Defines the `rollupNode` JSON-RPC namespace for rollup management operations. |
| 55 | +/// |
| 56 | +/// This trait provides a custom RPC namespace that exposes rollup node management |
| 57 | +/// functionality to external clients. The namespace is exposed as `rollupNode` and |
| 58 | +/// provides methods for controlling automatic sequencing behavior. |
| 59 | +/// |
| 60 | +/// # Usage |
| 61 | +/// These methods can be called via JSON-RPC using the `rollupNode` namespace: |
| 62 | +/// ```json |
| 63 | +/// {"jsonrpc": "2.0", "method": "rollupNode_enableAutomaticSequencing", "params": [], "id": 1} |
| 64 | +/// ``` |
| 65 | +/// or using cast: |
| 66 | +/// ```bash |
| 67 | +/// cast rpc rollupNode_enableAutomaticSequencing |
| 68 | +/// ``` |
| 69 | +#[rpc(server, client, namespace = "rollupNode")] |
| 70 | +pub trait RollupNodeExtApi { |
| 71 | + /// Enables automatic sequencing in the rollup node. |
| 72 | + #[method(name = "enableAutomaticSequencing")] |
| 73 | + async fn enable_automatic_sequencing(&self) -> RpcResult<bool>; |
| 74 | + |
| 75 | + /// Disables automatic sequencing in the rollup node. |
| 76 | + #[method(name = "disableAutomaticSequencing")] |
| 77 | + async fn disable_automatic_sequencing(&self) -> RpcResult<bool>; |
| 78 | +} |
| 79 | + |
| 80 | +#[async_trait] |
| 81 | +impl<N> RollupNodeExtApiServer for RollupNodeRpcExt<N> |
| 82 | +where |
| 83 | + N: FullNetwork<Primitives = ScrollNetworkPrimitives>, |
| 84 | +{ |
| 85 | + async fn enable_automatic_sequencing(&self) -> RpcResult<bool> { |
| 86 | + let handle = self.rollup_manager_handle().await.map_err(|e| { |
| 87 | + ErrorObjectOwned::owned( |
| 88 | + error::INTERNAL_ERROR_CODE, |
| 89 | + format!("Failed to get rollup manager handle: {}", e), |
| 90 | + None::<()>, |
| 91 | + ) |
| 92 | + })?; |
| 93 | + |
| 94 | + handle.enable_automatic_sequencing().await.map_err(|e| { |
| 95 | + ErrorObjectOwned::owned( |
| 96 | + error::INTERNAL_ERROR_CODE, |
| 97 | + format!("Failed to enable automatic sequencing: {}", e), |
| 98 | + None::<()>, |
| 99 | + ) |
| 100 | + }) |
| 101 | + } |
| 102 | + |
| 103 | + async fn disable_automatic_sequencing(&self) -> RpcResult<bool> { |
| 104 | + let handle = self.rollup_manager_handle().await.map_err(|e| { |
| 105 | + ErrorObjectOwned::owned( |
| 106 | + error::INTERNAL_ERROR_CODE, |
| 107 | + format!("Failed to get rollup manager handle: {}", e), |
| 108 | + None::<()>, |
| 109 | + ) |
| 110 | + })?; |
| 111 | + |
| 112 | + handle.disable_automatic_sequencing().await.map_err(|e| { |
| 113 | + ErrorObjectOwned::owned( |
| 114 | + error::INTERNAL_ERROR_CODE, |
| 115 | + format!("Failed to disable automatic sequencing: {}", e), |
| 116 | + None::<()>, |
| 117 | + ) |
| 118 | + }) |
| 119 | + } |
| 120 | +} |
0 commit comments