1use alloy_primitives::{Address, B256, U256};
9use jsonrpsee::{core::RpcResult, proc_macros::rpc};
10use serde::{Deserialize, Serialize};
11
12#[allow(dead_code)]
15mod u256_dec_or_hex {
16 use alloy_primitives::U256;
17 use serde::{self, Deserialize, Deserializer, Serializer};
18
19 pub fn serialize<S>(value: &U256, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: Serializer,
22 {
23 serde::Serialize::serialize(value, serializer)
24 }
25
26 pub fn deserialize<'de, D>(deserializer: D) -> Result<U256, D::Error>
27 where
28 D: Deserializer<'de>,
29 {
30 let v = serde_json::Value::deserialize(deserializer)?;
31 match v {
32 serde_json::Value::Number(n) => {
33 if let Some(u) = n.as_u64() {
34 Ok(U256::from(u))
35 } else {
36 U256::from_str_radix(&n.to_string(), 10).map_err(serde::de::Error::custom)
38 }
39 }
40 serde_json::Value::String(s) => {
41 if let Some(hex) = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")) {
42 U256::from_str_radix(hex, 16).map_err(serde::de::Error::custom)
43 } else {
44 U256::from_str_radix(&s, 10).map_err(serde::de::Error::custom)
45 }
46 }
47 _ => Err(serde::de::Error::custom(
48 "expected number or string for U256",
49 )),
50 }
51 }
52}
53
54mod opt_u256_dec_or_hex {
56 use alloy_primitives::U256;
57 use serde::{self, Deserialize, Deserializer, Serializer};
58
59 pub fn serialize<S>(value: &Option<U256>, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: Serializer,
62 {
63 match value {
64 Some(v) => serde::Serialize::serialize(v, serializer),
65 None => serializer.serialize_none(),
66 }
67 }
68
69 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
70 where
71 D: Deserializer<'de>,
72 {
73 let v = serde_json::Value::deserialize(deserializer)?;
74 match v {
75 serde_json::Value::Null => Ok(None),
76 serde_json::Value::Number(n) => {
77 if let Some(u) = n.as_u64() {
78 Ok(Some(U256::from(u)))
79 } else {
80 let val = U256::from_str_radix(&n.to_string(), 10)
81 .map_err(serde::de::Error::custom)?;
82 Ok(Some(val))
83 }
84 }
85 serde_json::Value::String(s) if s.is_empty() => Ok(None),
86 serde_json::Value::String(s) => {
87 let val = if let Some(hex) = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")) {
88 U256::from_str_radix(hex, 16).map_err(serde::de::Error::custom)?
89 } else {
90 U256::from_str_radix(&s, 10).map_err(serde::de::Error::custom)?
91 };
92 Ok(Some(val))
93 }
94 _ => Err(serde::de::Error::custom(
95 "expected number, string, or null for U256",
96 )),
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct RpcL1IncomingMessageHeader {
109 pub kind: u8,
110 pub sender: Address,
111 #[serde(rename = "blockNumber")]
112 pub block_number: u64,
113 pub timestamp: u64,
114 #[serde(default, skip_serializing_if = "Option::is_none", rename = "requestId")]
115 pub request_id: Option<B256>,
116 #[serde(
117 default,
118 skip_serializing_if = "Option::is_none",
119 rename = "baseFeeL1",
120 with = "opt_u256_dec_or_hex"
121 )]
122 pub base_fee_l1: Option<U256>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct RpcBatchDataStats {
129 pub length: u64,
130 pub nonzeros: u64,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct RpcL1IncomingMessage {
137 pub header: RpcL1IncomingMessageHeader,
138 #[serde(default, skip_serializing_if = "Option::is_none", rename = "l2Msg")]
140 pub l2_msg: Option<String>,
141 #[serde(
143 default,
144 skip_serializing_if = "Option::is_none",
145 rename = "batchGasCost"
146 )]
147 pub batch_gas_cost: Option<u64>,
148 #[serde(
150 default,
151 skip_serializing_if = "Option::is_none",
152 rename = "batchDataTokens"
153 )]
154 pub batch_data_tokens: Option<RpcBatchDataStats>,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct RpcMessageWithMetadata {
161 pub message: RpcL1IncomingMessage,
162 #[serde(rename = "delayedMessagesRead")]
163 pub delayed_messages_read: u64,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
169#[serde(rename_all = "PascalCase")]
170pub struct RpcMessageWithMetadataAndBlockInfo {
171 #[serde(rename = "MessageWithMeta")]
172 pub message: RpcMessageWithMetadata,
173 #[serde(default, skip_serializing_if = "Option::is_none")]
174 pub block_hash: Option<B256>,
175 #[serde(default, skip_serializing_if = "Option::is_none")]
176 pub block_metadata: Option<Vec<u8>>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
182#[serde(rename_all = "PascalCase")]
183pub struct RpcMessageResult {
184 pub block_hash: B256,
185 pub send_root: B256,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
191#[serde(rename_all = "PascalCase")]
192pub struct RpcFinalityData {
193 #[serde(default)]
194 pub msg_idx: u64,
195 #[serde(default)]
196 pub block_hash: B256,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
202#[serde(rename_all = "PascalCase")]
203pub struct RpcConsensusSyncData {
204 pub synced: bool,
205 pub max_message_count: u64,
206 #[serde(default)]
207 pub sync_progress_map: Option<serde_json::Value>,
208 #[serde(default)]
209 pub updated_at: Option<String>,
210}
211
212#[derive(Debug, Clone, Default, Serialize, Deserialize)]
215#[serde(rename_all = "PascalCase")]
216pub struct RpcMaintenanceStatus {
217 pub is_running: bool,
218}
219
220#[rpc(server, namespace = "nitroexecution")]
229pub trait NitroExecutionApi {
230 #[method(name = "digestMessage")]
232 async fn digest_message(
233 &self,
234 msg_idx: u64,
235 message: RpcMessageWithMetadata,
236 message_for_prefetch: Option<RpcMessageWithMetadata>,
237 ) -> RpcResult<RpcMessageResult>;
238
239 #[method(name = "reorg")]
241 async fn reorg(
242 &self,
243 msg_idx_of_first_msg_to_add: u64,
244 new_messages: Vec<RpcMessageWithMetadataAndBlockInfo>,
245 old_messages: Vec<RpcMessageWithMetadata>,
246 ) -> RpcResult<Vec<RpcMessageResult>>;
247
248 #[method(name = "headMessageIndex")]
250 async fn head_message_index(&self) -> RpcResult<u64>;
251
252 #[method(name = "resultAtMessageIndex")]
254 async fn result_at_message_index(&self, msg_idx: u64) -> RpcResult<RpcMessageResult>;
255
256 #[method(name = "setFinalityData")]
258 fn set_finality_data(
259 &self,
260 safe: Option<RpcFinalityData>,
261 finalized: Option<RpcFinalityData>,
262 validated: Option<RpcFinalityData>,
263 ) -> RpcResult<()>;
264
265 #[method(name = "setConsensusSyncData")]
267 fn set_consensus_sync_data(&self, sync_data: RpcConsensusSyncData) -> RpcResult<()>;
268
269 #[method(name = "markFeedStart")]
271 fn mark_feed_start(&self, to: u64) -> RpcResult<()>;
272
273 #[method(name = "triggerMaintenance")]
275 async fn trigger_maintenance(&self) -> RpcResult<()>;
276
277 #[method(name = "shouldTriggerMaintenance")]
279 async fn should_trigger_maintenance(&self) -> RpcResult<bool>;
280
281 #[method(name = "maintenanceStatus")]
283 async fn maintenance_status(&self) -> RpcResult<RpcMaintenanceStatus>;
284
285 #[method(name = "arbOSVersionForMessageIndex")]
287 async fn arbos_version_for_message_index(&self, msg_idx: u64) -> RpcResult<u64>;
288}