@@ -18,10 +18,10 @@ use lightning::routing::scoring::{
1818 ProbabilisticScorer , ProbabilisticScoringParameters ,
1919} ;
2020use lightning:: util:: ser:: { ReadableArgs , Writeable } ;
21- use tokio:: runtime :: Handle ;
21+ use tokio:: sync :: mpsc ;
2222use tracing:: { debug, error} ;
2323
24- use crate :: lexe:: channel_manager:: USER_CONFIG ;
24+ use crate :: lexe:: channel_manager:: { LxChannelMonitorUpdate , USER_CONFIG } ;
2525use crate :: lexe:: keys_manager:: LexeKeysManager ;
2626use crate :: lexe:: logger:: LexeTracingLogger ;
2727use crate :: lexe:: peer_manager:: ChannelPeer ;
@@ -53,8 +53,14 @@ impl LexePersister {
5353 api : ApiClientType ,
5454 node_pk : PublicKey ,
5555 measurement : Measurement ,
56+ channel_monitor_updated_tx : mpsc:: Sender < LxChannelMonitorUpdate > ,
5657 ) -> Self {
57- let inner = InnerPersister :: new ( api, node_pk, measurement) ;
58+ let inner = InnerPersister :: new (
59+ api,
60+ node_pk,
61+ measurement,
62+ channel_monitor_updated_tx,
63+ ) ;
5864 Self { inner }
5965 }
6066}
@@ -73,18 +79,21 @@ pub struct InnerPersister {
7379 api : ApiClientType ,
7480 node_pk : PublicKey ,
7581 measurement : Measurement ,
82+ channel_monitor_updated_tx : mpsc:: Sender < LxChannelMonitorUpdate > ,
7683}
7784
7885impl InnerPersister {
7986 fn new (
8087 api : ApiClientType ,
8188 node_pk : PublicKey ,
8289 measurement : Measurement ,
90+ channel_monitor_updated_tx : mpsc:: Sender < LxChannelMonitorUpdate > ,
8391 ) -> Self {
8492 Self {
8593 api,
8694 node_pk,
8795 measurement,
96+ channel_monitor_updated_tx,
8897 }
8998 }
9099
@@ -153,6 +162,7 @@ impl InnerPersister {
153162 keys_manager : LexeKeysManager ,
154163 ) -> anyhow:: Result < Vec < ( BlockHash , ChannelMonitorType ) > > {
155164 debug ! ( "Reading channel monitors" ) ;
165+ // TODO Also attempt to read from the cloud
156166
157167 let cm_dir = Directory {
158168 node_pk : self . node_pk ,
@@ -396,11 +406,10 @@ impl Persist<SignerType> for InnerPersister {
396406 & self ,
397407 funding_txo : OutPoint ,
398408 monitor : & ChannelMonitorType ,
399- _update_id : MonitorUpdateId ,
409+ update_id : MonitorUpdateId ,
400410 ) -> Result < ( ) , ChannelMonitorUpdateErr > {
401- let outpoint = LxOutPoint :: from ( funding_txo) ;
402- let outpoint_str = outpoint. to_string ( ) ;
403- debug ! ( "Persisting new channel {}" , outpoint_str) ;
411+ let funding_txo = LxOutPoint :: from ( funding_txo) ;
412+ debug ! ( "Persisting new channel {}" , funding_txo) ;
404413
405414 // FIXME(encrypt): Encrypt under key derived from seed
406415 let data = monitor. encode ( ) ;
@@ -409,31 +418,53 @@ impl Persist<SignerType> for InnerPersister {
409418 self . node_pk ,
410419 self . measurement ,
411420 CHANNEL_MONITORS_DIRECTORY . to_owned ( ) ,
412- outpoint_str ,
421+ funding_txo . to_string ( ) ,
413422 data,
414423 ) ;
424+ let update = LxChannelMonitorUpdate {
425+ funding_txo,
426+ update_id,
427+ } ;
415428
416- // Run an async fn inside a sync fn inside a Tokio runtime
417- Handle :: current ( )
418- . block_on ( async move { self . api . create_file ( & cm_file) . await } )
419- . map ( |_| ( ) )
420- . map_err ( |e| {
421- // TODO(max): Implement durability then make this err permanent
422- error ! ( "Could not persist new channel monitor: {:#}" , e) ;
423- ChannelMonitorUpdateErr :: TemporaryFailure
424- } )
429+ // Spawn a task for persisting the channel monitor
430+ let api_clone = self . api . clone ( ) ;
431+ let channel_monitor_updated_tx =
432+ self . channel_monitor_updated_tx . clone ( ) ;
433+ tokio:: spawn ( async move {
434+ // Retry indefinitely until it succeeds
435+ loop {
436+ // TODO Also attempt to persist to cloud backup
437+ match api_clone. create_file ( & cm_file) . await {
438+ Ok ( _file) => {
439+ if let Err ( e) =
440+ channel_monitor_updated_tx. try_send ( update)
441+ {
442+ error ! ( "Couldn't notify chain monitor: {:#}" , e) ;
443+ }
444+ return ;
445+ }
446+ Err ( e) => {
447+ error ! ( "Couldn't persist new channel monitor: {:#}" , e)
448+ }
449+ }
450+ }
451+ } ) ;
452+
453+ // As documented in the `Persist` trait docs, return `TemporaryFailure`,
454+ // which freezes the channel until persistence succeeds.
455+ Err ( ChannelMonitorUpdateErr :: TemporaryFailure )
425456 }
426457
427458 fn update_persisted_channel (
428459 & self ,
429460 funding_txo : OutPoint ,
461+ // TODO: We probably want to use this for rollback protection
430462 _update : & Option < ChannelMonitorUpdate > ,
431463 monitor : & ChannelMonitorType ,
432- _update_id : MonitorUpdateId ,
464+ update_id : MonitorUpdateId ,
433465 ) -> Result < ( ) , ChannelMonitorUpdateErr > {
434- let outpoint = LxOutPoint :: from ( funding_txo) ;
435- let outpoint_str = outpoint. to_string ( ) ;
436- debug ! ( "Updating persisted channel {}" , outpoint_str) ;
466+ let funding_txo = LxOutPoint :: from ( funding_txo) ;
467+ debug ! ( "Updating persisted channel {}" , funding_txo) ;
437468
438469 // FIXME(encrypt): Encrypt under key derived from seed
439470 let data = monitor. encode ( ) ;
@@ -442,18 +473,40 @@ impl Persist<SignerType> for InnerPersister {
442473 self . node_pk ,
443474 self . measurement ,
444475 CHANNEL_MONITORS_DIRECTORY . to_owned ( ) ,
445- outpoint_str ,
476+ funding_txo . to_string ( ) ,
446477 data,
447478 ) ;
479+ let update = LxChannelMonitorUpdate {
480+ funding_txo,
481+ update_id,
482+ } ;
448483
449- // Run an async fn inside a sync fn inside a Tokio runtime
450- Handle :: current ( )
451- . block_on ( async move { self . api . upsert_file ( & cm_file) . await } )
452- . map ( |_| ( ) )
453- . map_err ( |e| {
454- // TODO(max): Implement durability then make this err permanent
455- error ! ( "Could not update persisted channel monitor: {:#}" , e) ;
456- ChannelMonitorUpdateErr :: TemporaryFailure
457- } )
484+ // Spawn a task for persisting the channel monitor
485+ let api_clone = self . api . clone ( ) ;
486+ let channel_monitor_updated_tx =
487+ self . channel_monitor_updated_tx . clone ( ) ;
488+ tokio:: spawn ( async move {
489+ // Retry indefinitely until it succeeds
490+ loop {
491+ // TODO Also attempt to persist to cloud backup
492+ match api_clone. upsert_file ( & cm_file) . await {
493+ Ok ( _) => {
494+ if let Err ( e) =
495+ channel_monitor_updated_tx. try_send ( update)
496+ {
497+ error ! ( "Couldn't notify chain monitor: {:#}" , e) ;
498+ }
499+ return ;
500+ }
501+ Err ( e) => {
502+ error ! ( "Could not update channel monitor: {:#}" , e)
503+ }
504+ }
505+ }
506+ } ) ;
507+
508+ // As documented in the `Persist` trait docs, return `TemporaryFailure`,
509+ // which freezes the channel until persistence succeeds.
510+ Err ( ChannelMonitorUpdateErr :: TemporaryFailure )
458511 }
459512}
0 commit comments