11
11
//! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
12
12
13
13
use bitcoin:: { BlockHash , Txid } ;
14
+ use bitcoin:: hashes:: hex:: FromHex ;
14
15
use core:: cmp;
15
16
use core:: ops:: Deref ;
16
17
use core:: str:: FromStr ;
@@ -24,6 +25,7 @@ use crate::chain::chainmonitor::Persist;
24
25
use crate :: chain:: channelmonitor:: { ChannelMonitor , ChannelMonitorUpdate } ;
25
26
use crate :: chain:: transaction:: OutPoint ;
26
27
use crate :: ln:: channelmanager:: AChannelManager ;
28
+ use crate :: ln:: types:: ChannelId ;
27
29
use crate :: routing:: gossip:: NetworkGraph ;
28
30
use crate :: routing:: scoring:: WriteableScore ;
29
31
use crate :: sign:: { ecdsa:: EcdsaChannelSigner , EntropySource , SignerProvider } ;
@@ -896,9 +898,10 @@ where
896
898
/// A struct representing a name for a channel monitor.
897
899
///
898
900
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
899
- /// in functions that store or retrieve channel monitor snapshots.
901
+ /// in functions that store or retrieve [`ChannelMonitor`] snapshots.
900
902
/// It provides a consistent way to generate a unique key for channel
901
- /// monitors based on their funding outpoints.
903
+ /// monitors based on the channel's funding [`OutPoint`] for v1 channels or
904
+ /// [`ChannelId`] for v2 channels.
902
905
///
903
906
/// While users of the Lightning Dev Kit library generally won't need
904
907
/// to interact with [`MonitorName`] directly, it can be useful for:
@@ -912,30 +915,49 @@ where
912
915
/// use std::str::FromStr;
913
916
///
914
917
/// use bitcoin::Txid;
918
+ /// use bitcoin::hashes::hex::FromHex;
915
919
///
916
920
/// use lightning::util::persist::MonitorName;
917
921
/// use lightning::chain::transaction::OutPoint;
922
+ /// use lightning::ln::types::ChannelId;
918
923
///
924
+ /// // v1 channel
919
925
/// let outpoint = OutPoint {
920
926
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
921
927
/// index: 1,
922
928
/// };
923
929
/// let monitor_name = MonitorName::from(outpoint);
924
930
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
925
931
///
932
+ /// // v2 channel
933
+ /// let channel_id = ChannelId(<[u8; 32]>::from_hex("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap());
934
+ /// let monitor_name = MonitorName::from(channel_id);
935
+ /// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
936
+ ///
926
937
/// // Using MonitorName to generate a storage key
927
938
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
928
939
/// ```
929
940
#[ derive( Debug ) ]
930
941
pub struct MonitorName ( String ) ;
931
942
943
+ /// The source of the [`MonitorName`], either an [`OutPoint`] for V1 channels or a [`ChannelId`] for
944
+ /// V2 channels. The former uses the channel's funding outpoint for historical reasons. The latter
945
+ /// uses the channel's id because the funding outpoint may change during splicing.
946
+ pub enum MonitorNameSource {
947
+ /// The outpoint of the channel's funding transaction.
948
+ V1Channel ( OutPoint ) ,
949
+
950
+ /// The id of the channel produced by [`ChannelId::v2_from_revocation_basepoints`].
951
+ V2Channel ( ChannelId ) ,
952
+ }
953
+
932
954
impl MonitorName {
933
955
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
934
956
/// be formed from the given `name`.
935
957
/// This method is useful if you have a String and you want to verify that
936
958
/// it's a valid storage key for a channel monitor.
937
959
pub fn new ( name : String ) -> Result < Self , io:: Error > {
938
- MonitorName :: do_try_into_outpoint ( & name) ?;
960
+ MonitorNameSource :: try_from ( name. as_str ( ) ) ?;
939
961
Ok ( Self ( name) )
940
962
}
941
963
@@ -945,31 +967,48 @@ impl MonitorName {
945
967
pub fn as_str ( & self ) -> & str {
946
968
& self . 0
947
969
}
970
+ }
971
+
972
+ impl TryFrom < & str > for MonitorNameSource {
973
+ type Error = io:: Error ;
948
974
949
- /// Attempt to form a valid [`OutPoint`] from a given name string.
950
- fn do_try_into_outpoint ( name : & str ) -> Result < OutPoint , io:: Error > {
975
+ /// Attempts to convert a `MonitorName` back into an `OutPoint` or `ChannelId`.
976
+ ///
977
+ /// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
978
+ /// and need to reconstruct the original data it represents.
979
+ fn try_from ( name : & str ) -> Result < Self , io:: Error > {
951
980
let mut parts = name. splitn ( 2 , '_' ) ;
952
- let txid = if let Some ( part) = parts. next ( ) {
953
- Txid :: from_str ( part) . map_err ( |_| {
981
+ let id = parts
982
+ . next ( )
983
+ . ok_or_else ( || io:: Error :: new ( io:: ErrorKind :: InvalidData , "Empty stored key" ) ) ?;
984
+
985
+ if let Some ( part) = parts. next ( ) {
986
+ let txid = Txid :: from_str ( id) . map_err ( |_| {
954
987
io:: Error :: new ( io:: ErrorKind :: InvalidData , "Invalid tx ID in stored key" )
955
- } ) ?
956
- } else {
957
- return Err ( io:: Error :: new (
958
- io:: ErrorKind :: InvalidData ,
959
- "Stored monitor key is not a splittable string" ,
960
- ) ) ;
961
- } ;
962
- let index = if let Some ( part) = parts. next ( ) {
963
- part. parse ( ) . map_err ( |_| {
988
+ } ) ?;
989
+ let index: u16 = part. parse ( ) . map_err ( |_| {
964
990
io:: Error :: new ( io:: ErrorKind :: InvalidData , "Invalid tx index in stored key" )
965
- } ) ?
991
+ } ) ?;
992
+ let outpoint = OutPoint { txid, index } ;
993
+ Ok ( MonitorNameSource :: V1Channel ( outpoint) )
966
994
} else {
967
- return Err ( io:: Error :: new (
968
- io:: ErrorKind :: InvalidData ,
969
- "No tx index value found after underscore in stored key" ,
970
- ) ) ;
971
- } ;
972
- Ok ( OutPoint { txid, index } )
995
+ let bytes = <[ u8 ; 32 ] >:: from_hex ( id) . map_err ( |_| {
996
+ io:: Error :: new ( io:: ErrorKind :: InvalidData , "Invalid channel ID in stored key" )
997
+ } ) ?;
998
+ Ok ( MonitorNameSource :: V2Channel ( ChannelId ( bytes) ) )
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ impl TryFrom < & MonitorName > for MonitorNameSource {
1004
+ type Error = io:: Error ;
1005
+
1006
+ /// Attempts to convert a `MonitorName` back into an `OutPoint` or `ChannelId`.
1007
+ ///
1008
+ /// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
1009
+ /// and need to reconstruct the original data it represents.
1010
+ fn try_from ( value : & MonitorName ) -> Result < Self , io:: Error > {
1011
+ MonitorNameSource :: try_from ( value. 0 . as_str ( ) )
973
1012
}
974
1013
}
975
1014
@@ -981,20 +1020,34 @@ impl TryFrom<&MonitorName> for OutPoint {
981
1020
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
982
1021
/// and need to reconstruct the original `OutPoint` it represents.
983
1022
fn try_from ( value : & MonitorName ) -> Result < Self , io:: Error > {
984
- MonitorName :: do_try_into_outpoint ( & value. 0 )
1023
+ if let MonitorNameSource :: V1Channel ( outpoint) = MonitorNameSource :: try_from ( value) ? {
1024
+ Ok ( outpoint)
1025
+ } else {
1026
+ Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , "Invalid outpoint in stored key" ) )
1027
+ }
985
1028
}
986
1029
}
987
1030
988
1031
impl From < OutPoint > for MonitorName {
989
1032
/// Creates a `MonitorName` from an `OutPoint`.
990
1033
///
991
1034
/// This is typically used when you need to generate a storage key or identifier
992
- /// for a new or existing channel monitor.
1035
+ /// for a new or existing channel monitor for a v1 channel .
993
1036
fn from ( value : OutPoint ) -> Self {
994
1037
MonitorName ( format ! ( "{}_{}" , value. txid. to_string( ) , value. index) )
995
1038
}
996
1039
}
997
1040
1041
+ impl From < ChannelId > for MonitorName {
1042
+ /// Creates a `MonitorName` from a `ChannelId`.
1043
+ ///
1044
+ /// This is typically used when you need to generate a storage key or identifier
1045
+ /// for a new or existing channel monitor for a v2 channel.
1046
+ fn from ( id : ChannelId ) -> Self {
1047
+ MonitorName ( id. to_string ( ) )
1048
+ }
1049
+ }
1050
+
998
1051
/// A struct representing a name for a channel monitor update.
999
1052
///
1000
1053
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
@@ -1085,6 +1138,7 @@ impl From<u64> for UpdateName {
1085
1138
#[ cfg( test) ]
1086
1139
mod tests {
1087
1140
use super :: * ;
1141
+ use bitcoin:: hashes:: hex:: FromHex ;
1088
1142
use crate :: chain:: ChannelMonitorUpdateStatus ;
1089
1143
use crate :: events:: { ClosureReason , MessageSendEventsProvider } ;
1090
1144
use crate :: ln:: functional_test_utils:: * ;
@@ -1109,36 +1163,52 @@ mod tests {
1109
1163
}
1110
1164
1111
1165
#[ test]
1112
- fn monitor_from_outpoint_works ( ) {
1113
- let monitor_name1 = MonitorName :: from ( OutPoint {
1166
+ fn creates_monitor_from_outpoint ( ) {
1167
+ let monitor_name = MonitorName :: from ( OutPoint {
1114
1168
txid : Txid :: from_str (
1115
1169
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ,
1116
1170
)
1117
1171
. unwrap ( ) ,
1118
1172
index : 1 ,
1119
1173
} ) ;
1120
1174
assert_eq ! (
1121
- monitor_name1 . as_str( ) ,
1175
+ monitor_name . as_str( ) ,
1122
1176
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1"
1123
1177
) ;
1178
+ assert ! ( matches!( MonitorNameSource :: try_from( & monitor_name) , Ok ( MonitorNameSource :: V1Channel ( _) ) ) ) ;
1124
1179
1125
- let monitor_name2 = MonitorName :: from ( OutPoint {
1180
+ let monitor_name = MonitorName :: from ( OutPoint {
1126
1181
txid : Txid :: from_str (
1127
1182
"f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef" ,
1128
1183
)
1129
1184
. unwrap ( ) ,
1130
1185
index : u16:: MAX ,
1131
1186
} ) ;
1132
1187
assert_eq ! (
1133
- monitor_name2 . as_str( ) ,
1188
+ monitor_name . as_str( ) ,
1134
1189
"f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef_65535"
1135
1190
) ;
1191
+ assert ! ( matches!( MonitorNameSource :: try_from( & monitor_name) , Ok ( MonitorNameSource :: V1Channel ( _) ) ) ) ;
1192
+ }
1193
+
1194
+ #[ test]
1195
+ fn creates_monitor_from_channel_id ( ) {
1196
+ let monitor_name = MonitorName :: from (
1197
+ ChannelId ( <[ u8 ; 32 ] >:: from_hex (
1198
+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ,
1199
+ ) . unwrap ( ) )
1200
+ ) ;
1201
+ assert_eq ! (
1202
+ monitor_name. as_str( ) ,
1203
+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
1204
+ ) ;
1205
+ assert ! ( matches!( MonitorNameSource :: try_from( & monitor_name) , Ok ( MonitorNameSource :: V2Channel ( _) ) ) ) ;
1136
1206
}
1137
1207
1138
1208
#[ test]
1139
- fn bad_monitor_string_fails ( ) {
1209
+ fn fails_parsing_monitor_name ( ) {
1140
1210
assert ! ( MonitorName :: new(
1141
- "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef " . to_string( )
1211
+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_ " . to_string( )
1142
1212
)
1143
1213
. is_err( ) ) ;
1144
1214
assert ! ( MonitorName :: new(
0 commit comments