11use super :: * ;
22use crate :: config:: WALLET_KEYS_SEED_LEN ;
33
4- use crate :: logger:: log_error;
4+ use crate :: logger:: { log_error, FilesystemLogger } ;
55use crate :: peer_store:: PeerStore ;
6- use crate :: sweep:: SpendableOutputInfo ;
6+ use crate :: sweep:: DeprecatedSpendableOutputInfo ;
7+ use crate :: types:: { Broadcaster , ChainSource , FeeEstimator , KeysManager , Sweeper } ;
78use crate :: { Error , EventQueue , PaymentDetails } ;
89
910use lightning:: routing:: gossip:: NetworkGraph ;
@@ -12,13 +13,16 @@ use lightning::util::logger::Logger;
1213use lightning:: util:: persist:: {
1314 KVStore , KVSTORE_NAMESPACE_KEY_ALPHABET , KVSTORE_NAMESPACE_KEY_MAX_LEN ,
1415 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 ,
1720} ;
1821use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable } ;
1922use lightning:: util:: string:: PrintableString ;
2023
2124use bip39:: Mnemonic ;
25+ use lightning:: util:: sweep:: { OutputSpendStatus , OutputSweeper } ;
2226use rand:: { thread_rng, RngCore } ;
2327
2428use std:: fs;
@@ -200,34 +204,118 @@ where
200204 Ok ( res)
201205}
202206
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 >
207248where
208249 L :: Target : Logger ,
209250{
210- let mut res = Vec :: new ( ) ;
251+ let best_block = sweeper . current_best_block ( ) ;
211252
212253 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 ,
215256 ) ? {
216257 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 ,
219260 & stored_key,
220261 ) ?) ;
221- let output = SpendableOutputInfo :: read ( & mut reader) . map_err ( |e| {
262+ let output = DeprecatedSpendableOutputInfo :: read ( & mut reader) . map_err ( |e| {
222263 log_error ! ( logger, "Failed to deserialize SpendableOutputInfo: {}" , e) ;
223264 std:: io:: Error :: new (
224265 std:: io:: ErrorKind :: InvalidData ,
225266 "Failed to deserialize SpendableOutputInfo" ,
226267 )
227268 } ) ?;
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+ }
229316 }
230- Ok ( res)
317+
318+ Ok ( ( ) )
231319}
232320
233321pub ( crate ) fn read_latest_rgs_sync_timestamp < K : KVStore + Sync + Send , L : Deref > (
0 commit comments