1010//!
1111//! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
1212
13+ use bitcoin:: hashes:: hex:: FromHex ;
1314use bitcoin:: { BlockHash , Txid } ;
1415use core:: cmp;
1516use core:: ops:: Deref ;
@@ -24,6 +25,7 @@ use crate::chain::chainmonitor::Persist;
2425use crate :: chain:: channelmonitor:: { ChannelMonitor , ChannelMonitorUpdate } ;
2526use crate :: chain:: transaction:: OutPoint ;
2627use crate :: ln:: channelmanager:: AChannelManager ;
28+ use crate :: ln:: types:: ChannelId ;
2729use crate :: routing:: gossip:: NetworkGraph ;
2830use crate :: routing:: scoring:: WriteableScore ;
2931use crate :: sign:: { ecdsa:: EcdsaChannelSigner , EntropySource , SignerProvider } ;
@@ -896,9 +898,10 @@ where
896898/// A struct representing a name for a channel monitor.
897899///
898900/// `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.
900902/// 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.
902905///
903906/// While users of the Lightning Dev Kit library generally won't need
904907/// to interact with [`MonitorName`] directly, it can be useful for:
@@ -912,30 +915,49 @@ where
912915/// use std::str::FromStr;
913916///
914917/// use bitcoin::Txid;
918+ /// use bitcoin::hashes::hex::FromHex;
915919///
916920/// use lightning::util::persist::MonitorName;
917921/// use lightning::chain::transaction::OutPoint;
922+ /// use lightning::ln::types::ChannelId;
918923///
924+ /// // v1 channel
919925/// let outpoint = OutPoint {
920926/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
921927/// index: 1,
922928/// };
923929/// let monitor_name = MonitorName::from(outpoint);
924930/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
925931///
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+ ///
926937/// // Using MonitorName to generate a storage key
927938/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
928939/// ```
929940#[ derive( Debug ) ]
930941pub struct MonitorName ( String ) ;
931942
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+
932954impl MonitorName {
933955 /// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
934956 /// be formed from the given `name`.
935957 /// This method is useful if you have a String and you want to verify that
936958 /// it's a valid storage key for a channel monitor.
937959 pub fn new ( name : String ) -> Result < Self , io:: Error > {
938- MonitorName :: do_try_into_outpoint ( & name) ?;
960+ MonitorNameSource :: try_from ( name. as_str ( ) ) ?;
939961 Ok ( Self ( name) )
940962 }
941963
@@ -945,31 +967,48 @@ impl MonitorName {
945967 pub fn as_str ( & self ) -> & str {
946968 & self . 0
947969 }
970+ }
971+
972+ impl TryFrom < & str > for MonitorNameSource {
973+ type Error = io:: Error ;
948974
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 > {
951980 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 ( |_| {
954987 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 ( |_| {
964990 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) )
966994 } 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 ( ) )
9731012 }
9741013}
9751014
@@ -981,20 +1020,34 @@ impl TryFrom<&MonitorName> for OutPoint {
9811020 /// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
9821021 /// and need to reconstruct the original `OutPoint` it represents.
9831022 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+ }
9851028 }
9861029}
9871030
9881031impl From < OutPoint > for MonitorName {
9891032 /// Creates a `MonitorName` from an `OutPoint`.
9901033 ///
9911034 /// 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 .
9931036 fn from ( value : OutPoint ) -> Self {
9941037 MonitorName ( format ! ( "{}_{}" , value. txid. to_string( ) , value. index) )
9951038 }
9961039}
9971040
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+
9981051/// A struct representing a name for a channel monitor update.
9991052///
10001053/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
@@ -1092,6 +1145,7 @@ mod tests {
10921145 use crate :: util:: test_channel_signer:: TestChannelSigner ;
10931146 use crate :: util:: test_utils:: { self , TestLogger , TestStore } ;
10941147 use crate :: { check_added_monitors, check_closed_broadcast} ;
1148+ use bitcoin:: hashes:: hex:: FromHex ;
10951149
10961150 const EXPECTED_UPDATES_PER_PAYMENT : u64 = 5 ;
10971151
@@ -1109,36 +1163,62 @@ mod tests {
11091163 }
11101164
11111165 #[ 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 {
11141168 txid : Txid :: from_str (
11151169 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ,
11161170 )
11171171 . unwrap ( ) ,
11181172 index : 1 ,
11191173 } ) ;
11201174 assert_eq ! (
1121- monitor_name1 . as_str( ) ,
1175+ monitor_name . as_str( ) ,
11221176 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1"
11231177 ) ;
1178+ assert ! ( matches!(
1179+ MonitorNameSource :: try_from( & monitor_name) ,
1180+ Ok ( MonitorNameSource :: V1Channel ( _) )
1181+ ) ) ;
11241182
1125- let monitor_name2 = MonitorName :: from ( OutPoint {
1183+ let monitor_name = MonitorName :: from ( OutPoint {
11261184 txid : Txid :: from_str (
11271185 "f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef" ,
11281186 )
11291187 . unwrap ( ) ,
11301188 index : u16:: MAX ,
11311189 } ) ;
11321190 assert_eq ! (
1133- monitor_name2 . as_str( ) ,
1191+ monitor_name . as_str( ) ,
11341192 "f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef_65535"
11351193 ) ;
1194+ assert ! ( matches!(
1195+ MonitorNameSource :: try_from( & monitor_name) ,
1196+ Ok ( MonitorNameSource :: V1Channel ( _) )
1197+ ) ) ;
1198+ }
1199+
1200+ #[ test]
1201+ fn creates_monitor_from_channel_id ( ) {
1202+ let monitor_name = MonitorName :: from ( ChannelId (
1203+ <[ u8 ; 32 ] >:: from_hex (
1204+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ,
1205+ )
1206+ . unwrap ( ) ,
1207+ ) ) ;
1208+ assert_eq ! (
1209+ monitor_name. as_str( ) ,
1210+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
1211+ ) ;
1212+ assert ! ( matches!(
1213+ MonitorNameSource :: try_from( & monitor_name) ,
1214+ Ok ( MonitorNameSource :: V2Channel ( _) )
1215+ ) ) ;
11361216 }
11371217
11381218 #[ test]
1139- fn bad_monitor_string_fails ( ) {
1219+ fn fails_parsing_monitor_name ( ) {
11401220 assert ! ( MonitorName :: new(
1141- "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef " . to_string( )
1221+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_ " . to_string( )
11421222 )
11431223 . is_err( ) ) ;
11441224 assert ! ( MonitorName :: new(
0 commit comments