1
1
use super :: * ;
2
2
use crate :: config:: WALLET_KEYS_SEED_LEN ;
3
3
4
- use crate :: logger:: log_error;
4
+ use crate :: logger:: { log_error, FilesystemLogger } ;
5
5
use crate :: peer_store:: PeerStore ;
6
- use crate :: sweep:: SpendableOutputInfo ;
6
+ use crate :: sweep:: DeprecatedSpendableOutputInfo ;
7
+ use crate :: types:: { Broadcaster , ChainSource , FeeEstimator , KeysManager , Sweeper } ;
7
8
use crate :: { Error , EventQueue , PaymentDetails } ;
8
9
9
10
use lightning:: routing:: gossip:: NetworkGraph ;
@@ -12,13 +13,16 @@ use lightning::util::logger::Logger;
12
13
use lightning:: util:: persist:: {
13
14
KVStore , KVSTORE_NAMESPACE_KEY_ALPHABET , KVSTORE_NAMESPACE_KEY_MAX_LEN ,
14
15
NETWORK_GRAPH_PERSISTENCE_KEY , NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE ,
15
- NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , SCORER_PERSISTENCE_KEY ,
16
- SCORER_PERSISTENCE_PRIMARY_NAMESPACE , SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
16
+ NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_KEY ,
17
+ OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE ,
18
+ SCORER_PERSISTENCE_KEY , SCORER_PERSISTENCE_PRIMARY_NAMESPACE ,
19
+ SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
17
20
} ;
18
21
use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable } ;
19
22
use lightning:: util:: string:: PrintableString ;
20
23
21
24
use bip39:: Mnemonic ;
25
+ use lightning:: util:: sweep:: { OutputSpendStatus , OutputSweeper } ;
22
26
use rand:: { thread_rng, RngCore } ;
23
27
24
28
use std:: fs;
@@ -200,34 +204,118 @@ where
200
204
Ok ( res)
201
205
}
202
206
203
- /// Read previously persisted spendable output information from the store.
204
- pub ( crate ) fn read_spendable_outputs < K : KVStore + Sync + Send , L : Deref > (
205
- kv_store : Arc < K > , logger : L ,
206
- ) -> Result < Vec < SpendableOutputInfo > , std:: io:: Error >
207
+ /// Read `OutputSweeper` state from the store.
208
+ pub ( crate ) fn read_output_sweeper < K : KVStore + Send + Sync > (
209
+ broadcaster : Arc < Broadcaster > , fee_estimator : Arc < FeeEstimator > ,
210
+ chain_data_source : Arc < ChainSource > , keys_manager : Arc < KeysManager > , kv_store : Arc < K > ,
211
+ logger : Arc < FilesystemLogger > ,
212
+ ) -> Result < Sweeper < K > , std:: io:: Error > {
213
+ let mut reader = Cursor :: new ( kv_store. read (
214
+ OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
215
+ OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE ,
216
+ OUTPUT_SWEEPER_PERSISTENCE_KEY ,
217
+ ) ?) ;
218
+ let args = (
219
+ broadcaster,
220
+ fee_estimator,
221
+ Some ( chain_data_source) ,
222
+ Arc :: clone ( & keys_manager) ,
223
+ keys_manager,
224
+ kv_store,
225
+ logger. clone ( ) ,
226
+ ) ;
227
+ OutputSweeper :: read ( & mut reader, args) . map_err ( |e| {
228
+ log_error ! ( logger, "Failed to deserialize OutputSweeper: {}" , e) ;
229
+ std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidData , "Failed to deserialize OutputSweeper" )
230
+ } )
231
+ }
232
+
233
+ /// Read previously persisted spendable output information from the store and migrate to the
234
+ /// upstreamed `OutputSweeper`.
235
+ ///
236
+ /// We first iterate all `DeprecatedSpendableOutputInfo`s and have them tracked by the new
237
+ /// `OutputSweeper`. In order to be certain the initial output spends will happen in a single
238
+ /// transaction (and safe on-chain fees), we batch them to happen at current height plus two
239
+ /// blocks. Lastly, we remove the previously persisted data once we checked they are tracked and
240
+ /// awaiting their initial spend at the correct height.
241
+ ///
242
+ /// Note that this migration will be run in the `Builder`, i.e., at the time when the migration is
243
+ /// happening no background sync is ongoing, so we shouldn't have a risk of interleaving block
244
+ /// connections during the migration.
245
+ pub ( crate ) fn migrate_deprecated_spendable_outputs < K : KVStore + Sync + Send , L : Deref > (
246
+ sweeper : Arc < Sweeper < K > > , kv_store : Arc < K > , logger : L ,
247
+ ) -> Result < ( ) , std:: io:: Error >
207
248
where
208
249
L :: Target : Logger ,
209
250
{
210
- let mut res = Vec :: new ( ) ;
251
+ let best_block = sweeper . current_best_block ( ) ;
211
252
212
253
for stored_key in kv_store. list (
213
- SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
214
- SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
254
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
255
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
215
256
) ? {
216
257
let mut reader = Cursor :: new ( kv_store. read (
217
- SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
218
- SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
258
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
259
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
219
260
& stored_key,
220
261
) ?) ;
221
- let output = SpendableOutputInfo :: read ( & mut reader) . map_err ( |e| {
262
+ let output = DeprecatedSpendableOutputInfo :: read ( & mut reader) . map_err ( |e| {
222
263
log_error ! ( logger, "Failed to deserialize SpendableOutputInfo: {}" , e) ;
223
264
std:: io:: Error :: new (
224
265
std:: io:: ErrorKind :: InvalidData ,
225
266
"Failed to deserialize SpendableOutputInfo" ,
226
267
)
227
268
} ) ?;
228
- res. push ( output) ;
269
+ let descriptors = vec ! [ output. descriptor. clone( ) ] ;
270
+ let spend_delay = Some ( best_block. height + 2 ) ;
271
+ sweeper. track_spendable_outputs ( descriptors, output. channel_id , true , spend_delay) ;
272
+ if let Some ( tracked_spendable_output) =
273
+ sweeper. tracked_spendable_outputs ( ) . iter ( ) . find ( |o| o. descriptor == output. descriptor )
274
+ {
275
+ match tracked_spendable_output. status {
276
+ OutputSpendStatus :: PendingInitialBroadcast { delayed_until_height } => {
277
+ if delayed_until_height == spend_delay {
278
+ kv_store. remove (
279
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
280
+ DEPRECATED_SPENDABLE_OUTPUT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
281
+ & stored_key,
282
+ false ,
283
+ ) ?;
284
+ } else {
285
+ debug_assert ! ( false , "Unexpected status in OutputSweeper migration." ) ;
286
+ log_error ! ( logger, "Unexpected status in OutputSweeper migration." ) ;
287
+ return Err ( std:: io:: Error :: new (
288
+ std:: io:: ErrorKind :: Other ,
289
+ "Failed to migrate OutputSweeper state." ,
290
+ ) ) ;
291
+ }
292
+ } ,
293
+ _ => {
294
+ debug_assert ! ( false , "Unexpected status in OutputSweeper migration." ) ;
295
+ log_error ! ( logger, "Unexpected status in OutputSweeper migration." ) ;
296
+ return Err ( std:: io:: Error :: new (
297
+ std:: io:: ErrorKind :: Other ,
298
+ "Failed to migrate OutputSweeper state." ,
299
+ ) ) ;
300
+ } ,
301
+ }
302
+ } else {
303
+ debug_assert ! (
304
+ false ,
305
+ "OutputSweeper failed to track and persist outputs during migration."
306
+ ) ;
307
+ log_error ! (
308
+ logger,
309
+ "OutputSweeper failed to track and persist outputs during migration."
310
+ ) ;
311
+ return Err ( std:: io:: Error :: new (
312
+ std:: io:: ErrorKind :: Other ,
313
+ "Failed to migrate OutputSweeper state." ,
314
+ ) ) ;
315
+ }
229
316
}
230
- Ok ( res)
317
+
318
+ Ok ( ( ) )
231
319
}
232
320
233
321
pub ( crate ) fn read_latest_rgs_sync_timestamp < K : KVStore + Sync + Send , L : Deref > (
0 commit comments