miden_client/rpc/errors/node/
mod.rs1mod account;
2mod block;
3mod note;
4mod sync;
5mod transaction;
6
7pub use account::{GetAccountError, RegisterAccountError};
8pub use block::{GetBlockByNumberError, GetBlockHeaderError};
9pub use note::{GetNoteScriptByRootError, GetNotesByIdError};
10pub use sync::{
11 NoteSyncError,
12 SyncAccountStorageMapsError,
13 SyncAccountVaultError,
14 SyncChainMmrError,
15 SyncNullifiersError,
16 SyncTransactionsError,
17};
18use thiserror::Error;
19pub use transaction::AddTransactionError;
20
21use crate::rpc::RpcEndpoint;
22use crate::rpc::errors::GrpcError;
23
24#[derive(Debug, Clone, PartialEq, Eq, Error)]
28pub enum EndpointError {
29 #[error(transparent)]
31 AddTransaction(#[from] AddTransactionError),
32 #[error(transparent)]
34 GetBlockHeader(#[from] GetBlockHeaderError),
35 #[error(transparent)]
37 GetBlockByNumber(#[from] GetBlockByNumberError),
38 #[error(transparent)]
40 NoteSync(#[from] NoteSyncError),
41 #[error(transparent)]
43 SyncNullifiers(#[from] SyncNullifiersError),
44 #[error(transparent)]
46 SyncAccountVault(#[from] SyncAccountVaultError),
47 #[error(transparent)]
49 SyncStorageMaps(#[from] SyncAccountStorageMapsError),
50 #[error(transparent)]
52 SyncTransactions(#[from] SyncTransactionsError),
53 #[error(transparent)]
55 SyncChainMmr(#[from] SyncChainMmrError),
56 #[error(transparent)]
58 GetNotesById(#[from] GetNotesByIdError),
59 #[error(transparent)]
61 GetNoteScriptByRoot(#[from] GetNoteScriptByRootError),
62 #[error(transparent)]
64 GetAccount(#[from] GetAccountError),
65 #[error(transparent)]
67 RegisterAccount(#[from] RegisterAccountError),
68}
69
70pub fn parse_node_error(
74 endpoint: &RpcEndpoint,
75 details: &[u8],
76 message: &str,
77) -> Option<EndpointError> {
78 let code = *details.first()?;
79
80 match endpoint {
81 RpcEndpoint::SubmitProvenTx | RpcEndpoint::SubmitProvenBatch => {
82 Some(EndpointError::AddTransaction(AddTransactionError::from_code(code, message)))
83 },
84 RpcEndpoint::GetBlockHeaderByNumber => {
85 Some(EndpointError::GetBlockHeader(GetBlockHeaderError::from_code(code, message)))
86 },
87 RpcEndpoint::GetBlockByNumber => {
88 Some(EndpointError::GetBlockByNumber(GetBlockByNumberError::from_code(code, message)))
89 },
90 RpcEndpoint::SyncNotes => {
91 Some(EndpointError::NoteSync(NoteSyncError::from_code(code, message)))
92 },
93 RpcEndpoint::SyncNullifiers => {
94 Some(EndpointError::SyncNullifiers(SyncNullifiersError::from_code(code, message)))
95 },
96 RpcEndpoint::SyncAccountVault => {
97 Some(EndpointError::SyncAccountVault(SyncAccountVaultError::from_code(code, message)))
98 },
99 RpcEndpoint::SyncStorageMaps => Some(EndpointError::SyncStorageMaps(
100 SyncAccountStorageMapsError::from_code(code, message),
101 )),
102 RpcEndpoint::SyncTransactions => {
103 Some(EndpointError::SyncTransactions(SyncTransactionsError::from_code(code, message)))
104 },
105 RpcEndpoint::GetNotesById => {
106 Some(EndpointError::GetNotesById(GetNotesByIdError::from_code(code, message)))
107 },
108 RpcEndpoint::GetNoteScriptByRoot => Some(EndpointError::GetNoteScriptByRoot(
109 GetNoteScriptByRootError::from_code(code, message),
110 )),
111 RpcEndpoint::GetAccount => {
112 Some(EndpointError::GetAccount(GetAccountError::from_code(code, message)))
113 },
114 RpcEndpoint::SyncChainMmr => {
115 Some(EndpointError::SyncChainMmr(SyncChainMmrError::from_code(code, message)))
116 },
117 RpcEndpoint::Status
119 | RpcEndpoint::GetLimits
120 | RpcEndpoint::GetNetworkNoteStatus
121 | RpcEndpoint::GetTransactionEncryptionKey
122 | RpcEndpoint::RegisterAccount
123 | RpcEndpoint::IsAccountAllowed => None,
124 }
125}
126
127pub fn parse_status_error(
129 endpoint: &RpcEndpoint,
130 error_kind: &GrpcError,
131 message: &str,
132) -> Option<EndpointError> {
133 match endpoint {
136 RpcEndpoint::RegisterAccount => RegisterAccountError::from_grpc_error(error_kind, message)
137 .map(EndpointError::RegisterAccount),
138 RpcEndpoint::SubmitProvenTx
139 | RpcEndpoint::GetBlockHeaderByNumber
140 | RpcEndpoint::GetBlockByNumber
141 | RpcEndpoint::SyncNotes
142 | RpcEndpoint::SyncNullifiers
143 | RpcEndpoint::SyncAccountVault
144 | RpcEndpoint::SyncStorageMaps
145 | RpcEndpoint::SyncTransactions
146 | RpcEndpoint::GetNotesById
147 | RpcEndpoint::GetNoteScriptByRoot
148 | RpcEndpoint::GetAccount
149 | RpcEndpoint::SyncChainMmr
150 | RpcEndpoint::Status
151 | RpcEndpoint::GetLimits
152 | RpcEndpoint::GetNetworkNoteStatus
153 | RpcEndpoint::GetTransactionEncryptionKey
154 | RpcEndpoint::IsAccountAllowed
155 | RpcEndpoint::SubmitProvenBatch => None,
156 }
157}
158
159#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
170 fn only_the_register_account_endpoint_classifies_a_status_code() {
171 let registration =
172 parse_status_error(&RpcEndpoint::RegisterAccount, &GrpcError::NotFound, "unknown");
173
174 assert!(matches!(
175 registration,
176 Some(EndpointError::RegisterAccount(RegisterAccountError::InvitationNotFound))
177 ));
178
179 for endpoint in [
180 RpcEndpoint::GetAccount,
181 RpcEndpoint::SubmitProvenTx,
182 RpcEndpoint::GetNotesById,
183 RpcEndpoint::Status,
184 ] {
185 assert!(
186 parse_status_error(&endpoint, &GrpcError::NotFound, "unknown").is_none(),
187 "{endpoint:?} must not classify a status code"
188 );
189 }
190 }
191
192 #[test]
195 fn a_transport_failure_on_the_registration_endpoint_stays_unclassified() {
196 assert!(
197 parse_status_error(
198 &RpcEndpoint::RegisterAccount,
199 &GrpcError::Unavailable,
200 "node is down"
201 )
202 .is_none()
203 );
204 }
205
206 #[test]
209 fn a_block_after_the_chain_tip_parses_as_future_block() {
210 let message = "block_to (5) is greater than chain tip (4)";
211 assert_eq!(
212 parse_node_error(&RpcEndpoint::SyncNotes, &[2], message),
213 Some(EndpointError::NoteSync(NoteSyncError::FutureBlock))
214 );
215 assert_eq!(
216 parse_node_error(&RpcEndpoint::SyncChainMmr, &[2], message),
217 Some(EndpointError::SyncChainMmr(SyncChainMmrError::FutureBlock))
218 );
219 assert_eq!(
220 parse_node_error(&RpcEndpoint::SyncNullifiers, &[4], message),
221 Some(EndpointError::SyncNullifiers(SyncNullifiersError::FutureBlock))
222 );
223 assert_eq!(
224 parse_node_error(&RpcEndpoint::SyncAccountVault, &[4], message),
225 Some(EndpointError::SyncAccountVault(SyncAccountVaultError::FutureBlock))
226 );
227 assert_eq!(
228 parse_node_error(&RpcEndpoint::SyncStorageMaps, &[5], message),
229 Some(EndpointError::SyncStorageMaps(SyncAccountStorageMapsError::FutureBlock))
230 );
231 assert_eq!(
232 parse_node_error(&RpcEndpoint::SyncTransactions, &[5], message),
233 Some(EndpointError::SyncTransactions(SyncTransactionsError::FutureBlock))
234 );
235 }
236}