@@ -764,6 +764,201 @@ impl Readable for IrrevocablyResolvedHTLC {
764
764
}
765
765
}
766
766
767
+ /// [StubChannel] is the smallest unit of [OurPeerStorage], it contains
768
+ /// information about a single channel using which we can recover on-chain funds.
769
+ #[ derive( Clone , PartialEq , Eq ) ]
770
+ pub struct StubChannel {
771
+ pub ( crate ) channel_id : ChannelId ,
772
+ pub ( crate ) funding_outpoint : OutPoint ,
773
+ pub ( crate ) channel_value_stoshis : u64 ,
774
+ pub ( crate ) channel_keys_id : [ u8 ; 32 ] ,
775
+ pub ( crate ) commitment_secrets : CounterpartyCommitmentSecrets ,
776
+ pub ( crate ) counterparty_node_id : PublicKey ,
777
+ pub ( crate ) counterparty_delayed_payment_base_key : DelayedPaymentBasepoint ,
778
+ pub ( crate ) counterparty_htlc_base_key : HtlcBasepoint ,
779
+ pub ( crate ) on_counterparty_tx_csv : u16 ,
780
+ pub ( crate ) obscure_factor : u64 ,
781
+ pub ( crate ) latest_state : HashMap < Txid , Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > > ,
782
+ pub ( crate ) their_cur_per_commitment_points : Option < ( u64 , PublicKey , Option < PublicKey > ) > ,
783
+ pub ( crate ) features : ChannelTypeFeatures ,
784
+ }
785
+
786
+ impl StubChannel {
787
+ pub ( crate ) fn new ( channel_id : ChannelId , funding_outpoint : OutPoint , channel_value_stoshis : u64 , channel_keys_id : [ u8 ; 32 ] ,
788
+ commitment_secrets : CounterpartyCommitmentSecrets , counterparty_node_id : PublicKey , counterparty_delayed_payment_base_key : DelayedPaymentBasepoint , counterparty_htlc_base_key : HtlcBasepoint , on_counterparty_tx_csv : u16 ,
789
+ obscure_factor : u64 , latest_state : HashMap < Txid , Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > > , their_cur_per_commitment_points : Option < ( u64 , PublicKey , Option < PublicKey > ) > ,
790
+ features : ChannelTypeFeatures ) -> Self {
791
+ StubChannel {
792
+ channel_id,
793
+ funding_outpoint,
794
+ channel_value_stoshis,
795
+ channel_keys_id,
796
+ commitment_secrets,
797
+ counterparty_node_id,
798
+ counterparty_delayed_payment_base_key,
799
+ counterparty_htlc_base_key,
800
+ on_counterparty_tx_csv,
801
+ obscure_factor,
802
+ latest_state,
803
+ their_cur_per_commitment_points,
804
+ features,
805
+ }
806
+ }
807
+
808
+ pub fn get_min_seen_secret ( & self ) -> u64 {
809
+ return self . commitment_secrets . get_min_seen_secret ( ) ;
810
+ }
811
+ }
812
+
813
+ impl_writeable_tlv_based ! ( StubChannel , {
814
+ ( 0 , channel_id, required) ,
815
+ ( 2 , channel_keys_id, required) ,
816
+ ( 4 , channel_value_stoshis, required) ,
817
+ ( 6 , funding_outpoint, required) ,
818
+ ( 8 , commitment_secrets, required) ,
819
+ ( 10 , counterparty_node_id, required) ,
820
+ ( 12 , counterparty_delayed_payment_base_key, required) ,
821
+ ( 14 , counterparty_htlc_base_key, required) ,
822
+ ( 16 , on_counterparty_tx_csv, required) ,
823
+ ( 18 , obscure_factor, required) ,
824
+ ( 20 , latest_state, required) ,
825
+ ( 22 , their_cur_per_commitment_points, option) ,
826
+ ( 24 , features, required) ,
827
+ } ) ;
828
+
829
+ /// [OurPeerStorage] is used to store our channels using which we
830
+ /// can create our PeerStorage Backup.
831
+ /// This includes timestamp to compare between two given
832
+ /// [OurPeerStorage] and version defines the structure.
833
+ #[ derive( Clone , PartialEq , Eq ) ]
834
+ pub struct OurPeerStorage {
835
+ version : u32 ,
836
+ timestamp : u32 ,
837
+ channels : Vec < StubChannel > ,
838
+ }
839
+
840
+ impl OurPeerStorage {
841
+ pub fn new ( ) -> Self {
842
+ let duration_since_epoch = std:: time:: SystemTime :: now ( )
843
+ . duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
844
+ . expect ( "Time must be > 1970" ) ;
845
+
846
+ Self {
847
+ version : 1 ,
848
+ timestamp : duration_since_epoch. as_secs ( ) as u32 ,
849
+ channels : Vec :: new ( ) ,
850
+ }
851
+ }
852
+
853
+ pub fn stub_channel ( & mut self , chan : StubChannel ) {
854
+ self . channels . push ( chan) ;
855
+ }
856
+
857
+ pub fn get_channels ( & self ) -> & Vec < StubChannel > {
858
+ self . channels . as_ref ( )
859
+ }
860
+
861
+ pub ( crate ) fn update_latest_state ( & mut self , cid : ChannelId , txid : Txid , htlc_data : Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > , their_cur_per_commitment_points : Option < ( u64 , PublicKey , Option < PublicKey > ) > ) {
862
+ for stub_channel in & mut self . channels {
863
+ if stub_channel. channel_id == cid {
864
+ let mut latest_state = HashMap :: new ( ) ;
865
+ latest_state. insert ( txid, htlc_data) ;
866
+ stub_channel. latest_state = latest_state;
867
+ stub_channel. their_cur_per_commitment_points = their_cur_per_commitment_points;
868
+ return ;
869
+ }
870
+ }
871
+ }
872
+
873
+ pub ( crate ) fn provide_secret ( & mut self , cid : ChannelId , idx : u64 , secret : [ u8 ; 32 ] ) -> Result < ( ) , ( ) > {
874
+ for stub_channel in & mut self . channels {
875
+ if stub_channel. channel_id == cid {
876
+ return stub_channel. commitment_secrets . provide_secret ( idx, secret) ;
877
+ }
878
+ }
879
+ return Err ( ( ) ) ;
880
+ }
881
+
882
+ /// This is called to update the data of the latest state inside [`OurPeerStorage`] using
883
+ /// [`ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo`]
884
+ pub ( crate ) fn update_state_from_monitor_update ( & mut self , cid : ChannelId , monitor_update : ChannelMonitorUpdate ) -> Result < ( ) , ( ) > {
885
+ for update in monitor_update. updates . iter ( ) {
886
+ match update {
887
+ ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number,
888
+ their_per_commitment_point, .. } => {
889
+ let stub_channels = & self . channels ;
890
+ let mut cur_per_commitment_points = None ;
891
+ for stub_channel in stub_channels {
892
+ if stub_channel. channel_id == cid {
893
+ match stub_channel. their_cur_per_commitment_points {
894
+ Some ( old_points) => {
895
+ if old_points. 0 == commitment_number + 1 {
896
+ cur_per_commitment_points = Some ( ( old_points. 0 , old_points. 1 , Some ( * their_per_commitment_point) ) ) ;
897
+ } else if old_points. 0 == commitment_number + 2 {
898
+ if let Some ( old_second_point) = old_points. 2 {
899
+ cur_per_commitment_points = Some ( ( old_points. 0 - 1 , old_second_point, Some ( * their_per_commitment_point) ) ) ;
900
+ } else {
901
+ cur_per_commitment_points = Some ( ( * commitment_number, * their_per_commitment_point, None ) ) ;
902
+ }
903
+ } else {
904
+ cur_per_commitment_points = Some ( ( * commitment_number, * their_per_commitment_point, None ) ) ;
905
+ }
906
+ } ,
907
+ None => {
908
+ cur_per_commitment_points = Some ( ( * commitment_number, * their_per_commitment_point, None ) ) ;
909
+ }
910
+ }
911
+ }
912
+ }
913
+ let mut htlc_data = htlc_outputs. clone ( ) ;
914
+ for htlc in & mut htlc_data {
915
+ htlc. 1 = None ;
916
+ }
917
+ self . update_latest_state ( cid, * commitment_txid, htlc_data, cur_per_commitment_points) ;
918
+ return Ok ( ( ) ) ;
919
+ }
920
+ _ => { }
921
+ }
922
+ }
923
+ Err ( ( ) )
924
+ }
925
+
926
+ pub fn encrypt_our_peer_storage ( & self , key : [ u8 ; 32 ] ) -> Vec < u8 > {
927
+ let n = 0u64 ;
928
+ let mut peer_storage = VecWriter ( Vec :: new ( ) ) ;
929
+ self . write ( & mut peer_storage) . unwrap ( ) ;
930
+ let mut res = vec ! [ 0 ; peer_storage. 0 . len( ) + 16 ] ;
931
+
932
+ let plaintext = & peer_storage. 0 [ ..] ;
933
+ let mut nonce = [ 0 ; 12 ] ;
934
+ nonce[ 4 ..] . copy_from_slice ( & n. to_le_bytes ( ) [ ..] ) ;
935
+
936
+ let mut chacha = ChaCha20Poly1305RFC :: new ( & key, & nonce, b"" ) ;
937
+ let mut tag = [ 0 ; 16 ] ;
938
+ chacha. encrypt ( plaintext, & mut res[ 0 ..plaintext. len ( ) ] , & mut tag) ;
939
+ res[ plaintext. len ( ) ..] . copy_from_slice ( & tag) ;
940
+ res
941
+ }
942
+
943
+ pub fn decrypt_our_peer_storage ( & self , res : & mut [ u8 ] , cyphertext : & [ u8 ] , key : [ u8 ; 32 ] ) -> Result < ( ) , ( ) > {
944
+ let n = 0u64 ;
945
+ let mut nonce = [ 0 ; 12 ] ;
946
+ nonce[ 4 ..] . copy_from_slice ( & n. to_le_bytes ( ) [ ..] ) ;
947
+
948
+ let mut chacha = ChaCha20Poly1305RFC :: new ( & key, & nonce, b"" ) ;
949
+ if chacha. variable_time_decrypt ( & cyphertext[ 0 ..cyphertext. len ( ) - 16 ] , res, & cyphertext[ cyphertext. len ( ) - 16 ..] ) . is_err ( ) {
950
+ return Err ( ( ) ) ;
951
+ }
952
+ Ok ( ( ) )
953
+ }
954
+ }
955
+
956
+ impl_writeable_tlv_based ! ( OurPeerStorage , {
957
+ ( 0 , version, ( default_value, 1 ) ) ,
958
+ ( 2 , timestamp, required) ,
959
+ ( 4 , channels, optional_vec) ,
960
+ } ) ;
961
+
767
962
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
768
963
/// on-chain transactions to ensure no loss of funds occurs.
769
964
///
@@ -1458,6 +1653,19 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
1458
1653
self . inner . lock ( ) . unwrap ( ) . get_latest_update_id ( )
1459
1654
}
1460
1655
1656
+ /// Gets the latest claiming info from the ChannelMonitor to update our PeerStorageBackup.
1657
+ pub ( crate ) fn get_latest_commitment_txn_and_its_claiming_info ( & self ) -> Option < ( Txid , Vec < ( HTLCOutputInCommitment , Option < std:: boxed:: Box < HTLCSource > > ) > , Option < ( u64 , PublicKey , Option < PublicKey > ) > ) > {
1658
+ let lock = self . inner . lock ( ) . unwrap ( ) ;
1659
+ if let Some ( latest_txid) = lock. current_counterparty_commitment_txid {
1660
+ return Some ( (
1661
+ latest_txid, lock. counterparty_claimable_outpoints . get ( & latest_txid) . unwrap ( ) . clone ( ) ,
1662
+ lock. their_cur_per_commitment_points
1663
+ ) )
1664
+ }
1665
+
1666
+ None
1667
+ }
1668
+
1461
1669
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
1462
1670
pub fn get_funding_txo ( & self ) -> ( OutPoint , ScriptBuf ) {
1463
1671
self . inner . lock ( ) . unwrap ( ) . get_funding_txo ( ) . clone ( )
0 commit comments