22
33use std:: { error, fmt, io} ;
44
5- use bitcoin:: hex;
6-
7- /// The error type for errors produced in this library.
5+ /// The general error type for the async client.
6+ ///
7+ /// This covers connecting, authenticating, and performing a JSON-RPC call. Each RPC method returns
8+ /// its own error type (e.g. [`GetBlockError`]) which wraps this type in its `Rpc` variant.
89#[ derive( Debug ) ]
910pub enum Error {
11+ /// A JSON-RPC error occurred (transport error or the node returned an error).
1012 JsonRpc ( jsonrpc:: error:: Error ) ,
11- HexToArray ( hex:: HexToArrayError ) ,
12- HexToBytes ( hex:: HexToBytesError ) ,
13+ /// Serializing an argument or deserializing the response failed.
1314 Json ( serde_json:: error:: Error ) ,
14- BitcoinSerialization ( bitcoin :: consensus :: encode :: FromHexError ) ,
15+ /// An I/O error occurred (e.g. reading the cookie file).
1516 Io ( io:: Error ) ,
17+ /// The cookie file was invalid.
1618 InvalidCookieFile ,
17- /// The JSON result had an unexpected structure.
18- UnexpectedStructure ,
19- /// The daemon returned an error string.
20- Returned ( String ) ,
2119 /// The server version did not match what was expected.
2220 ServerVersion ( UnexpectedServerVersionError ) ,
2321 /// Missing user/password.
@@ -28,22 +26,10 @@ impl From<jsonrpc::error::Error> for Error {
2826 fn from ( e : jsonrpc:: error:: Error ) -> Error { Error :: JsonRpc ( e) }
2927}
3028
31- impl From < hex:: HexToArrayError > for Error {
32- fn from ( e : hex:: HexToArrayError ) -> Self { Self :: HexToArray ( e) }
33- }
34-
35- impl From < hex:: HexToBytesError > for Error {
36- fn from ( e : hex:: HexToBytesError ) -> Self { Self :: HexToBytes ( e) }
37- }
38-
3929impl From < serde_json:: error:: Error > for Error {
4030 fn from ( e : serde_json:: error:: Error ) -> Error { Error :: Json ( e) }
4131}
4232
43- impl From < bitcoin:: consensus:: encode:: FromHexError > for Error {
44- fn from ( e : bitcoin:: consensus:: encode:: FromHexError ) -> Error { Error :: BitcoinSerialization ( e) }
45- }
46-
4733impl From < io:: Error > for Error {
4834 fn from ( e : io:: Error ) -> Error { Error :: Io ( e) }
4935}
@@ -54,14 +40,9 @@ impl fmt::Display for Error {
5440
5541 match * self {
5642 JsonRpc ( ref e) => write ! ( f, "JSON-RPC error: {}" , e) ,
57- HexToArray ( ref e) => write ! ( f, "hex to array decode error: {}" , e) ,
58- HexToBytes ( ref e) => write ! ( f, "hex to bytes decode error: {}" , e) ,
5943 Json ( ref e) => write ! ( f, "JSON error: {}" , e) ,
60- BitcoinSerialization ( ref e) => write ! ( f, "Bitcoin serialization error: {}" , e) ,
6144 Io ( ref e) => write ! ( f, "I/O error: {}" , e) ,
6245 InvalidCookieFile => write ! ( f, "invalid cookie file" ) ,
63- UnexpectedStructure => write ! ( f, "the JSON result had an unexpected structure" ) ,
64- Returned ( ref s) => write ! ( f, "the daemon returned an error string: {}" , s) ,
6546 ServerVersion ( ref e) => write ! ( f, "server version: {}" , e) ,
6647 MissingUserPassword => write ! ( f, "missing user and/or password" ) ,
6748 }
@@ -74,17 +55,203 @@ impl error::Error for Error {
7455
7556 match * self {
7657 JsonRpc ( ref e) => Some ( e) ,
77- HexToArray ( ref e) => Some ( e) ,
78- HexToBytes ( ref e) => Some ( e) ,
7958 Json ( ref e) => Some ( e) ,
80- BitcoinSerialization ( ref e) => Some ( e) ,
8159 Io ( ref e) => Some ( e) ,
8260 ServerVersion ( ref e) => Some ( e) ,
83- InvalidCookieFile | UnexpectedStructure | Returned ( _ ) | MissingUserPassword => None ,
61+ InvalidCookieFile | MissingUserPassword => None ,
8462 }
8563 }
8664}
8765
66+ /// Defines the error type returned by a single RPC method on the async `Client`.
67+ ///
68+ /// Every method error has an `Rpc` variant, holding the [`Error`] from making the call. Methods
69+ /// that convert the response into a model type additionally have a `Model` variant holding the
70+ /// conversion error. There are three forms:
71+ ///
72+ /// - `Name => Type`: `Model` holds the concrete conversion error `Type`.
73+ /// - `Name => boxed`: `Model` holds a boxed error. Used by methods that select a version specific
74+ /// type at runtime and so have no single concrete conversion error type.
75+ /// - `Name`: no `Model` variant, for methods whose response conversion cannot fail.
76+ macro_rules! define_method_error {
77+ // Version-agnostic (boxed) model conversion error.
78+ ( $( #[ $doc: meta] ) * $name: ident => boxed) => {
79+ $( #[ $doc] ) *
80+ #[ derive( Debug ) ]
81+ pub enum $name {
82+ /// Making the JSON-RPC call failed.
83+ Rpc ( Error ) ,
84+ /// Converting the returned JSON into the model type failed.
85+ Model ( Box <dyn std:: error:: Error + Send + Sync + ' static >) ,
86+ }
87+
88+ impl From <Error > for $name {
89+ fn from( e: Error ) -> Self { Self :: Rpc ( e) }
90+ }
91+
92+ impl From <serde_json:: error:: Error > for $name {
93+ fn from( e: serde_json:: error:: Error ) -> Self { Self :: Rpc ( Error :: Json ( e) ) }
94+ }
95+
96+ impl fmt:: Display for $name {
97+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
98+ match * self {
99+ Self :: Rpc ( ref e) => write!( f, "JSON-RPC call failed: {}" , e) ,
100+ Self :: Model ( ref e) => write!( f, "conversion to the model type failed: {}" , e) ,
101+ }
102+ }
103+ }
104+
105+ impl error:: Error for $name {
106+ fn source( & self ) -> Option <& ( dyn std:: error:: Error + ' static ) > {
107+ match * self {
108+ Self :: Rpc ( ref e) => Some ( e) ,
109+ Self :: Model ( ref e) => Some ( & * * e) ,
110+ }
111+ }
112+ }
113+ } ;
114+ // Strongly typed model conversion error.
115+ ( $( #[ $doc: meta] ) * $name: ident => $model: ty) => {
116+ $( #[ $doc] ) *
117+ #[ derive( Debug ) ]
118+ pub enum $name {
119+ /// Making the JSON-RPC call failed.
120+ Rpc ( Error ) ,
121+ /// Converting the returned JSON into the model type failed.
122+ Model ( $model) ,
123+ }
124+
125+ impl From <Error > for $name {
126+ fn from( e: Error ) -> Self { Self :: Rpc ( e) }
127+ }
128+
129+ impl From <serde_json:: error:: Error > for $name {
130+ fn from( e: serde_json:: error:: Error ) -> Self { Self :: Rpc ( Error :: Json ( e) ) }
131+ }
132+
133+ impl fmt:: Display for $name {
134+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
135+ match * self {
136+ Self :: Rpc ( ref e) => write!( f, "JSON-RPC call failed: {}" , e) ,
137+ Self :: Model ( ref e) => write!( f, "conversion to the model type failed: {}" , e) ,
138+ }
139+ }
140+ }
141+
142+ impl error:: Error for $name {
143+ fn source( & self ) -> Option <& ( dyn std:: error:: Error + ' static ) > {
144+ match * self {
145+ Self :: Rpc ( ref e) => Some ( e) ,
146+ Self :: Model ( ref e) => Some ( e) ,
147+ }
148+ }
149+ }
150+ } ;
151+ // RPC failure only (response conversion cannot fail).
152+ ( $( #[ $doc: meta] ) * $name: ident) => {
153+ $( #[ $doc] ) *
154+ #[ derive( Debug ) ]
155+ pub enum $name {
156+ /// Making the JSON-RPC call failed.
157+ Rpc ( Error ) ,
158+ }
159+
160+ impl From <Error > for $name {
161+ fn from( e: Error ) -> Self { Self :: Rpc ( e) }
162+ }
163+
164+ impl From <serde_json:: error:: Error > for $name {
165+ fn from( e: serde_json:: error:: Error ) -> Self { Self :: Rpc ( Error :: Json ( e) ) }
166+ }
167+
168+ impl fmt:: Display for $name {
169+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
170+ match * self {
171+ Self :: Rpc ( ref e) => write!( f, "JSON-RPC call failed: {}" , e) ,
172+ }
173+ }
174+ }
175+
176+ impl error:: Error for $name {
177+ fn source( & self ) -> Option <& ( dyn std:: error:: Error + ' static ) > {
178+ match * self {
179+ Self :: Rpc ( ref e) => Some ( e) ,
180+ }
181+ }
182+ }
183+ } ;
184+ }
185+
186+ define_method_error ! {
187+ /// Error returned by [`Client::get_block`](crate::client_async::Client::get_block).
188+ GetBlockError => bitcoin:: consensus:: encode:: FromHexError
189+ }
190+
191+ define_method_error ! {
192+ /// Error returned by [`Client::get_block_count`](crate::client_async::Client::get_block_count).
193+ GetBlockCountError
194+ }
195+
196+ define_method_error ! {
197+ /// Error returned by [`Client::server_version`](crate::client_async::Client::server_version).
198+ ServerVersionError
199+ }
200+
201+ define_method_error ! {
202+ /// Error returned by [`Client::get_block_hash`](crate::client_async::Client::get_block_hash).
203+ GetBlockHashError => bitcoin:: hex:: HexToArrayError
204+ }
205+
206+ define_method_error ! {
207+ /// Error returned by
208+ /// [`Client::get_best_block_hash`](crate::client_async::Client::get_best_block_hash).
209+ GetBestBlockHashError => bitcoin:: hex:: HexToArrayError
210+ }
211+
212+ define_method_error ! {
213+ /// Error returned by [`Client::get_block_header`](crate::client_async::Client::get_block_header).
214+ GetBlockHeaderError => types:: v17:: GetBlockHeaderError
215+ }
216+
217+ define_method_error ! {
218+ /// Error returned by
219+ /// [`Client::get_block_header_verbose`](crate::client_async::Client::get_block_header_verbose).
220+ GetBlockHeaderVerboseError => boxed
221+ }
222+
223+ define_method_error ! {
224+ /// Error returned by [`Client::get_block_verbose`](crate::client_async::Client::get_block_verbose).
225+ GetBlockVerboseError => boxed
226+ }
227+
228+ define_method_error ! {
229+ /// Error returned by [`Client::get_block_filter`](crate::client_async::Client::get_block_filter).
230+ GetBlockFilterError => types:: v19:: GetBlockFilterError
231+ }
232+
233+ define_method_error ! {
234+ /// Error returned by [`Client::get_raw_mempool`](crate::client_async::Client::get_raw_mempool).
235+ GetRawMempoolError => bitcoin:: hex:: HexToArrayError
236+ }
237+
238+ define_method_error ! {
239+ /// Error returned by
240+ /// [`Client::get_raw_transaction`](crate::client_async::Client::get_raw_transaction).
241+ GetRawTransactionError => bitcoin:: consensus:: encode:: FromHexError
242+ }
243+
244+ define_method_error ! {
245+ /// Error returned by
246+ /// [`Client::get_blockchain_info`](crate::client_async::Client::get_blockchain_info).
247+ GetBlockchainInfoError => boxed
248+ }
249+
250+ define_method_error ! {
251+ /// Error returned by [`Client::get_tx_out`](crate::client_async::Client::get_tx_out).
252+ GetTxOutError => types:: v17:: GetTxOutError
253+ }
254+
88255/// Error returned when RPC client expects a different version than bitcoind reports.
89256#[ derive( Debug , Clone , PartialEq , Eq ) ]
90257pub struct UnexpectedServerVersionError {
0 commit comments