1
1
//! Adapters that make one or more [`BlockSource`]s simpler to poll for new chain tip transitions.
2
2
3
- use crate :: { AsyncBlockSourceResult , BlockData , BlockHeaderData , BlockSource , BlockSourceError , BlockSourceResult } ;
3
+ use crate :: {
4
+ AsyncBlockSourceResult , BlockData , BlockHeaderData , BlockSource , BlockSourceError ,
5
+ BlockSourceResult ,
6
+ } ;
4
7
5
8
use bitcoin:: hash_types:: BlockHash ;
6
9
use bitcoin:: network:: Network ;
@@ -17,16 +20,19 @@ use std::ops::Deref;
17
20
/// [`ChainPoller`]: ../struct.ChainPoller.html
18
21
pub trait Poll {
19
22
/// Returns a chain tip in terms of its relationship to the provided chain tip.
20
- fn poll_chain_tip < ' a > ( & ' a self , best_known_chain_tip : ValidatedBlockHeader ) ->
21
- AsyncBlockSourceResult < ' a , ChainTip > ;
23
+ fn poll_chain_tip < ' a > (
24
+ & ' a self , best_known_chain_tip : ValidatedBlockHeader ,
25
+ ) -> AsyncBlockSourceResult < ' a , ChainTip > ;
22
26
23
27
/// Returns the header that preceded the given header in the chain.
24
- fn look_up_previous_header < ' a > ( & ' a self , header : & ' a ValidatedBlockHeader ) ->
25
- AsyncBlockSourceResult < ' a , ValidatedBlockHeader > ;
28
+ fn look_up_previous_header < ' a > (
29
+ & ' a self , header : & ' a ValidatedBlockHeader ,
30
+ ) -> AsyncBlockSourceResult < ' a , ValidatedBlockHeader > ;
26
31
27
32
/// Returns the block associated with the given header.
28
- fn fetch_block < ' a > ( & ' a self , header : & ' a ValidatedBlockHeader ) ->
29
- AsyncBlockSourceResult < ' a , ValidatedBlock > ;
33
+ fn fetch_block < ' a > (
34
+ & ' a self , header : & ' a ValidatedBlockHeader ,
35
+ ) -> AsyncBlockSourceResult < ' a , ValidatedBlock > ;
30
36
}
31
37
32
38
/// A chain tip relative to another chain tip in terms of block hash and chainwork.
@@ -59,9 +65,8 @@ impl Validate for BlockHeaderData {
59
65
type T = ValidatedBlockHeader ;
60
66
61
67
fn validate ( self , block_hash : BlockHash ) -> BlockSourceResult < Self :: T > {
62
- let pow_valid_block_hash = self . header
63
- . validate_pow ( self . header . target ( ) )
64
- . map_err ( BlockSourceError :: persistent) ?;
68
+ let pow_valid_block_hash =
69
+ self . header . validate_pow ( self . header . target ( ) ) . map_err ( BlockSourceError :: persistent) ?;
65
70
66
71
if pow_valid_block_hash != block_hash {
67
72
return Err ( BlockSourceError :: persistent ( "invalid block hash" ) ) ;
@@ -80,9 +85,8 @@ impl Validate for BlockData {
80
85
BlockData :: HeaderOnly ( header) => header,
81
86
} ;
82
87
83
- let pow_valid_block_hash = header
84
- . validate_pow ( header. target ( ) )
85
- . map_err ( BlockSourceError :: persistent) ?;
88
+ let pow_valid_block_hash =
89
+ header. validate_pow ( header. target ( ) ) . map_err ( BlockSourceError :: persistent) ?;
86
90
87
91
if pow_valid_block_hash != block_hash {
88
92
return Err ( BlockSourceError :: persistent ( "invalid block hash" ) ) ;
@@ -120,7 +124,9 @@ impl std::ops::Deref for ValidatedBlockHeader {
120
124
impl ValidatedBlockHeader {
121
125
/// Checks that the header correctly builds on previous_header: the claimed work differential
122
126
/// matches the actual PoW and the difficulty transition is possible, i.e., within 4x.
123
- fn check_builds_on ( & self , previous_header : & ValidatedBlockHeader , network : Network ) -> BlockSourceResult < ( ) > {
127
+ fn check_builds_on (
128
+ & self , previous_header : & ValidatedBlockHeader , network : Network ,
129
+ ) -> BlockSourceResult < ( ) > {
124
130
if self . header . prev_blockhash != previous_header. block_hash {
125
131
return Err ( BlockSourceError :: persistent ( "invalid previous block hash" ) ) ;
126
132
}
@@ -141,28 +147,28 @@ impl ValidatedBlockHeader {
141
147
let min_target = previous_target. min_difficulty_transition_threshold ( ) ;
142
148
let max_target = previous_target. max_difficulty_transition_threshold ( ) ;
143
149
if target > max_target || target < min_target {
144
- return Err ( BlockSourceError :: persistent ( "invalid difficulty transition" ) )
150
+ return Err ( BlockSourceError :: persistent ( "invalid difficulty transition" ) ) ;
145
151
}
146
152
} else if self . header . bits != previous_header. header . bits {
147
- return Err ( BlockSourceError :: persistent ( "invalid difficulty" ) )
153
+ return Err ( BlockSourceError :: persistent ( "invalid difficulty" ) ) ;
148
154
}
149
155
}
150
156
151
157
Ok ( ( ) )
152
158
}
153
159
154
- /// Returns the [`BestBlock`] corresponding to this validated block header, which can be passed
155
- /// into [`ChannelManager::new`] as part of its [`ChainParameters`]. Useful for ensuring that
156
- /// the [`SpvClient`] and [`ChannelManager`] are initialized to the same block during a fresh
157
- /// start.
158
- ///
159
- /// [`SpvClient`]: crate::SpvClient
160
- /// [`ChainParameters`]: lightning::ln::channelmanager::ChainParameters
161
- /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
162
- /// [`ChannelManager::new`]: lightning::ln::channelmanager::ChannelManager::new
163
- pub fn to_best_block ( & self ) -> BestBlock {
164
- BestBlock :: new ( self . block_hash , self . inner . height )
165
- }
160
+ /// Returns the [`BestBlock`] corresponding to this validated block header, which can be passed
161
+ /// into [`ChannelManager::new`] as part of its [`ChainParameters`]. Useful for ensuring that
162
+ /// the [`SpvClient`] and [`ChannelManager`] are initialized to the same block during a fresh
163
+ /// start.
164
+ ///
165
+ /// [`SpvClient`]: crate::SpvClient
166
+ /// [`ChainParameters`]: lightning::ln::channelmanager::ChainParameters
167
+ /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
168
+ /// [`ChannelManager::new`]: lightning::ln::channelmanager::ChannelManager::new
169
+ pub fn to_best_block ( & self ) -> BestBlock {
170
+ BestBlock :: new ( self . block_hash , self . inner . height )
171
+ }
166
172
}
167
173
168
174
/// A block with validated data against its transaction list and corresponding block hash.
@@ -191,12 +197,12 @@ mod sealed {
191
197
///
192
198
/// Other `Poll` implementations should be built using `ChainPoller` as it provides the simplest way
193
199
/// of validating chain data and checking consistency.
194
- pub struct ChainPoller < B : Deref < Target = T > + Sized + Send + Sync , T : BlockSource + ?Sized > {
200
+ pub struct ChainPoller < B : Deref < Target = T > + Sized + Send + Sync , T : BlockSource + ?Sized > {
195
201
block_source : B ,
196
202
network : Network ,
197
203
}
198
204
199
- impl < B : Deref < Target = T > + Sized + Send + Sync , T : BlockSource + ?Sized > ChainPoller < B , T > {
205
+ impl < B : Deref < Target = T > + Sized + Send + Sync , T : BlockSource + ?Sized > ChainPoller < B , T > {
200
206
/// Creates a new poller for the given block source.
201
207
///
202
208
/// If the `network` parameter is mainnet, then the difficulty between blocks is checked for
@@ -206,19 +212,20 @@ impl<B: Deref<Target=T> + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPol
206
212
}
207
213
}
208
214
209
- impl < B : Deref < Target =T > + Sized + Send + Sync , T : BlockSource + ?Sized > Poll for ChainPoller < B , T > {
210
- fn poll_chain_tip < ' a > ( & ' a self , best_known_chain_tip : ValidatedBlockHeader ) ->
211
- AsyncBlockSourceResult < ' a , ChainTip >
212
- {
215
+ impl < B : Deref < Target = T > + Sized + Send + Sync , T : BlockSource + ?Sized > Poll
216
+ for ChainPoller < B , T >
217
+ {
218
+ fn poll_chain_tip < ' a > (
219
+ & ' a self , best_known_chain_tip : ValidatedBlockHeader ,
220
+ ) -> AsyncBlockSourceResult < ' a , ChainTip > {
213
221
Box :: pin ( async move {
214
222
let ( block_hash, height) = self . block_source . get_best_block ( ) . await ?;
215
223
if block_hash == best_known_chain_tip. header . block_hash ( ) {
216
224
return Ok ( ChainTip :: Common ) ;
217
225
}
218
226
219
- let chain_tip = self . block_source
220
- . get_header ( & block_hash, height) . await ?
221
- . validate ( block_hash) ?;
227
+ let chain_tip =
228
+ self . block_source . get_header ( & block_hash, height) . await ?. validate ( block_hash) ?;
222
229
if chain_tip. chainwork > best_known_chain_tip. chainwork {
223
230
Ok ( ChainTip :: Better ( chain_tip) )
224
231
} else {
@@ -227,41 +234,41 @@ impl<B: Deref<Target=T> + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for
227
234
} )
228
235
}
229
236
230
- fn look_up_previous_header < ' a > ( & ' a self , header : & ' a ValidatedBlockHeader ) ->
231
- AsyncBlockSourceResult < ' a , ValidatedBlockHeader >
232
- {
237
+ fn look_up_previous_header < ' a > (
238
+ & ' a self , header : & ' a ValidatedBlockHeader ,
239
+ ) -> AsyncBlockSourceResult < ' a , ValidatedBlockHeader > {
233
240
Box :: pin ( async move {
234
241
if header. height == 0 {
235
242
return Err ( BlockSourceError :: persistent ( "genesis block reached" ) ) ;
236
243
}
237
244
238
245
let previous_hash = & header. header . prev_blockhash ;
239
246
let height = header. height - 1 ;
240
- let previous_header = self . block_source
241
- . get_header ( previous_hash, Some ( height) ) . await ?
247
+ let previous_header = self
248
+ . block_source
249
+ . get_header ( previous_hash, Some ( height) )
250
+ . await ?
242
251
. validate ( * previous_hash) ?;
243
252
header. check_builds_on ( & previous_header, self . network ) ?;
244
253
245
254
Ok ( previous_header)
246
255
} )
247
256
}
248
257
249
- fn fetch_block < ' a > ( & ' a self , header : & ' a ValidatedBlockHeader ) ->
250
- AsyncBlockSourceResult < ' a , ValidatedBlock >
251
- {
258
+ fn fetch_block < ' a > (
259
+ & ' a self , header : & ' a ValidatedBlockHeader ,
260
+ ) -> AsyncBlockSourceResult < ' a , ValidatedBlock > {
252
261
Box :: pin ( async move {
253
- self . block_source
254
- . get_block ( & header. block_hash ) . await ?
255
- . validate ( header. block_hash )
262
+ self . block_source . get_block ( & header. block_hash ) . await ?. validate ( header. block_hash )
256
263
} )
257
264
}
258
265
}
259
266
260
267
#[ cfg( test) ]
261
268
mod tests {
262
- use crate :: * ;
263
- use crate :: test_utils:: Blockchain ;
264
269
use super :: * ;
270
+ use crate :: test_utils:: Blockchain ;
271
+ use crate :: * ;
265
272
266
273
#[ tokio:: test]
267
274
async fn poll_empty_chain ( ) {
@@ -307,7 +314,10 @@ mod tests {
307
314
match poller. poll_chain_tip ( best_known_chain_tip) . await {
308
315
Err ( e) => {
309
316
assert_eq ! ( e. kind( ) , BlockSourceErrorKind :: Persistent ) ;
310
- assert_eq ! ( e. into_inner( ) . as_ref( ) . to_string( ) , "block target correct but not attained" ) ;
317
+ assert_eq ! (
318
+ e. into_inner( ) . as_ref( ) . to_string( ) ,
319
+ "block target correct but not attained"
320
+ ) ;
311
321
} ,
312
322
Ok ( _) => panic ! ( "Expected error" ) ,
313
323
}
0 commit comments