1
1
//! Simple REST client implementation which implements [`BlockSource`] against a Bitcoin Core REST
2
2
//! endpoint.
3
3
4
- use crate :: { BlockData , BlockHeaderData , BlockSource , AsyncBlockSourceResult } ;
5
- use crate :: http:: { BinaryResponse , HttpEndpoint , HttpClient , JsonResponse } ;
6
- use crate :: gossip:: UtxoSource ;
7
4
use crate :: convert:: GetUtxosResponse ;
5
+ use crate :: gossip:: UtxoSource ;
6
+ use crate :: http:: { BinaryResponse , HttpClient , HttpEndpoint , JsonResponse } ;
7
+ use crate :: { AsyncBlockSourceResult , BlockData , BlockHeaderData , BlockSource } ;
8
8
9
- use bitcoin:: OutPoint ;
10
9
use bitcoin:: hash_types:: BlockHash ;
10
+ use bitcoin:: OutPoint ;
11
11
12
12
use std:: convert:: TryFrom ;
13
13
use std:: convert:: TryInto ;
@@ -29,41 +29,54 @@ impl RestClient {
29
29
30
30
/// Requests a resource encoded in `F` format and interpreted as type `T`.
31
31
pub async fn request_resource < F , T > ( & self , resource_path : & str ) -> std:: io:: Result < T >
32
- where F : TryFrom < Vec < u8 > , Error = std:: io:: Error > + TryInto < T , Error = std:: io:: Error > {
32
+ where
33
+ F : TryFrom < Vec < u8 > , Error = std:: io:: Error > + TryInto < T , Error = std:: io:: Error > ,
34
+ {
33
35
let host = format ! ( "{}:{}" , self . endpoint. host( ) , self . endpoint. port( ) ) ;
34
36
let uri = format ! ( "{}/{}" , self . endpoint. path( ) . trim_end_matches( "/" ) , resource_path) ;
35
- let mut client = if let Some ( client) = self . client . lock ( ) . unwrap ( ) . take ( ) { client }
36
- else { HttpClient :: connect ( & self . endpoint ) ? } ;
37
+ let mut client = if let Some ( client) = self . client . lock ( ) . unwrap ( ) . take ( ) {
38
+ client
39
+ } else {
40
+ HttpClient :: connect ( & self . endpoint ) ?
41
+ } ;
37
42
let res = client. get :: < F > ( & uri, & host) . await ?. try_into ( ) ;
38
43
* self . client . lock ( ) . unwrap ( ) = Some ( client) ;
39
44
res
40
45
}
41
46
}
42
47
43
48
impl BlockSource for RestClient {
44
- fn get_header < ' a > ( & ' a self , header_hash : & ' a BlockHash , _height : Option < u32 > ) -> AsyncBlockSourceResult < ' a , BlockHeaderData > {
49
+ fn get_header < ' a > (
50
+ & ' a self , header_hash : & ' a BlockHash , _height : Option < u32 > ,
51
+ ) -> AsyncBlockSourceResult < ' a , BlockHeaderData > {
45
52
Box :: pin ( async move {
46
53
let resource_path = format ! ( "headers/1/{}.json" , header_hash. to_string( ) ) ;
47
54
Ok ( self . request_resource :: < JsonResponse , _ > ( & resource_path) . await ?)
48
55
} )
49
56
}
50
57
51
- fn get_block < ' a > ( & ' a self , header_hash : & ' a BlockHash ) -> AsyncBlockSourceResult < ' a , BlockData > {
58
+ fn get_block < ' a > (
59
+ & ' a self , header_hash : & ' a BlockHash ,
60
+ ) -> AsyncBlockSourceResult < ' a , BlockData > {
52
61
Box :: pin ( async move {
53
62
let resource_path = format ! ( "block/{}.bin" , header_hash. to_string( ) ) ;
54
- Ok ( BlockData :: FullBlock ( self . request_resource :: < BinaryResponse , _ > ( & resource_path) . await ?) )
63
+ Ok ( BlockData :: FullBlock (
64
+ self . request_resource :: < BinaryResponse , _ > ( & resource_path) . await ?,
65
+ ) )
55
66
} )
56
67
}
57
68
58
69
fn get_best_block < ' a > ( & ' a self ) -> AsyncBlockSourceResult < ' a , ( BlockHash , Option < u32 > ) > {
59
- Box :: pin ( async move {
60
- Ok ( self . request_resource :: < JsonResponse , _ > ( "chaininfo.json" ) . await ?)
61
- } )
70
+ Box :: pin (
71
+ async move { Ok ( self . request_resource :: < JsonResponse , _ > ( "chaininfo.json" ) . await ?) } ,
72
+ )
62
73
}
63
74
}
64
75
65
76
impl UtxoSource for RestClient {
66
- fn get_block_hash_by_height < ' a > ( & ' a self , block_height : u32 ) -> AsyncBlockSourceResult < ' a , BlockHash > {
77
+ fn get_block_hash_by_height < ' a > (
78
+ & ' a self , block_height : u32 ,
79
+ ) -> AsyncBlockSourceResult < ' a , BlockHash > {
67
80
Box :: pin ( async move {
68
81
let resource_path = format ! ( "blockhashbyheight/{}.bin" , block_height) ;
69
82
Ok ( self . request_resource :: < BinaryResponse , _ > ( & resource_path) . await ?)
@@ -72,7 +85,8 @@ impl UtxoSource for RestClient {
72
85
73
86
fn is_output_unspent < ' a > ( & ' a self , outpoint : OutPoint ) -> AsyncBlockSourceResult < ' a , bool > {
74
87
Box :: pin ( async move {
75
- let resource_path = format ! ( "getutxos/{}-{}.json" , outpoint. txid. to_string( ) , outpoint. vout) ;
88
+ let resource_path =
89
+ format ! ( "getutxos/{}-{}.json" , outpoint. txid. to_string( ) , outpoint. vout) ;
76
90
let utxo_result =
77
91
self . request_resource :: < JsonResponse , GetUtxosResponse > ( & resource_path) . await ?;
78
92
Ok ( utxo_result. hit_bitmap_nonempty )
@@ -83,8 +97,8 @@ impl UtxoSource for RestClient {
83
97
#[ cfg( test) ]
84
98
mod tests {
85
99
use super :: * ;
86
- use crate :: http:: BinaryResponse ;
87
100
use crate :: http:: client_tests:: { HttpServer , MessageBody } ;
101
+ use crate :: http:: BinaryResponse ;
88
102
use bitcoin:: hashes:: Hash ;
89
103
90
104
/// Parses binary data as a string-encoded `u32`.
@@ -97,7 +111,7 @@ mod tests {
97
111
Ok ( s) => match u32:: from_str_radix ( s, 10 ) {
98
112
Err ( e) => Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidData , e) ) ,
99
113
Ok ( n) => Ok ( n) ,
100
- }
114
+ } ,
101
115
}
102
116
}
103
117
}
@@ -140,7 +154,7 @@ mod tests {
140
154
let server = HttpServer :: responding_with_ok ( MessageBody :: Content (
141
155
// A real response contains a few more fields, but we actually only look at the
142
156
// "bitmap" field, so this should suffice for testing
143
- "{\" chainHeight\" : 1, \" bitmap\" :\" 0\" ,\" utxos\" :[]}"
157
+ "{\" chainHeight\" : 1, \" bitmap\" :\" 0\" ,\" utxos\" :[]}" ,
144
158
) ) ;
145
159
let client = RestClient :: new ( server. endpoint ( ) ) . unwrap ( ) ;
146
160
@@ -154,7 +168,7 @@ mod tests {
154
168
let server = HttpServer :: responding_with_ok ( MessageBody :: Content (
155
169
// A real response contains lots more data, but we actually only look at the "bitmap"
156
170
// field, so this should suffice for testing
157
- "{\" chainHeight\" : 1, \" bitmap\" :\" 1\" ,\" utxos\" :[]}"
171
+ "{\" chainHeight\" : 1, \" bitmap\" :\" 1\" ,\" utxos\" :[]}" ,
158
172
) ) ;
159
173
let client = RestClient :: new ( server. endpoint ( ) ) . unwrap ( ) ;
160
174
0 commit comments