Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions lightning/src/util/persist.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -728,7 +728,7 @@ where
/// - No full monitor is found in [`KVStore`]
/// - The number of pending updates exceeds `maximum_pending_updates` as given to [`Self::new`]
/// - LDK commands re-persisting the entire monitor through this function, specifically when
///`update` is `None`.
///`update` is `None`.
/// - The update is at [`CLOSED_CHANNEL_UPDATE_ID`]
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
Expand DownExpand Up@@ -859,21 +859,59 @@ where
}
}

/// A struct representing a name for a monitor.
/// A struct representing a name for a channel monitor.
///
/// `MonitorName` is primarily used within the [`MonitorUpdatingPersister`]
/// in functions that store or retrieve channel monitor snapshots.
/// It provides a consistent way to generate a unique key for channel
/// monitors based on their funding outpoints.
///
/// While users of the Lightning Dev Kit library generally won't need
/// to interact with [`MonitorName`] directly, it can be useful for:
/// - Custom persistence implementations
/// - Debugging or logging channel monitor operations
/// - Extending the functionality of the `MonitorUpdatingPersister`
//
/// # Examples
///
/// ```
/// use std::str::FromStr;
///
/// use bitcoin::Txid;
///
/// use lightning::util::persist::MonitorName;
/// use lightning::chain::transaction::OutPoint;
///
/// let outpoint = OutPoint {
/// txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
/// index: 1,
/// };
/// let monitor_name = MonitorName::from(outpoint);
/// assert_eq!(monitor_name.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1");
///
/// // Using MonitorName to generate a storage key
/// let storage_key = format!("channel_monitors/{}", monitor_name.as_str());
/// ```
#[derive(Debug)]
struct MonitorName(String);
pub struct MonitorName(String);

impl MonitorName {
/// Constructs a [`MonitorName`], after verifying that an [`OutPoint`] can
/// be formed from the given `name`.
/// This method is useful if you have a String and you want to verify that
/// it's a valid storage key for a channel monitor.
pub fn new(name: String) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&name)?;
Ok(Self(name))
}

/// Convert this monitor name to a str.
/// This method is particularly useful when you need to use the monitor name
/// as a key in a key-value store or when logging.
pub fn as_str(&self) -> &str {
&self.0
}

/// Attempt to form a valid [`OutPoint`] from a given name string.
fn do_try_into_outpoint(name: &str) -> Result<OutPoint, io::Error> {
let mut parts = name.splitn(2, '_');
Expand DownExpand Up@@ -904,20 +942,60 @@ impl MonitorName {
impl TryFrom<&MonitorName> for OutPoint {
type Error = io::Error;

/// Attempts to convert a `MonitorName` back into an `OutPoint`.
///
/// This is useful when you have a `MonitorName` (perhaps retrieved from storage)
/// and need to reconstruct the original `OutPoint` it represents.
fn try_from(value: &MonitorName) -> Result<Self, io::Error> {
MonitorName::do_try_into_outpoint(&value.0)
}
}

impl From<OutPoint> for MonitorName {
/// Creates a `MonitorName` from an `OutPoint`.
///
/// This is typically used when you need to generate a storage key or identifier
/// for a new or existing channel monitor.
fn from(value: OutPoint) -> Self {
MonitorName(format!("{}_{}", value.txid.to_string(), value.index))
}
}

/// A struct representing a name for an update.
/// A struct representing a name for a channel monitor update.
///
/// [`UpdateName`] is primarily used within the [`MonitorUpdatingPersister`] in
/// functions that store or retrieve partial updates to channel monitors. It
/// provides a consistent way to generate and parse unique identifiers for
/// monitor updates based on their sequence number.
///
/// The name is derived from the update's sequence ID, which is a monotonically
/// increasing u64 value. This format allows for easy ordering of updates and
/// efficient storage and retrieval in key-value stores.
///
/// # Usage
///
/// While users of the Lightning Dev Kit library generally won't need to
/// interact with `UpdateName` directly, it still can be useful for custom
/// persistence implementations. The u64 value is the update_id that can be
/// compared with [ChannelMonitor::get_latest_update_id] to check if this update
/// has been applied to the channel monitor or not, which is useful for pruning
/// stale channel monitor updates off persistence.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
///
/// // Using UpdateName to generate a storage key
/// let monitor_name = "some_monitor_name";
/// let storage_key = format!("channel_monitor_updates/{}/{}", monitor_name, update_name.as_str());
/// ```
#[derive(Debug)]
struct UpdateName(u64, String);
pub struct UpdateName(pub u64, String);

impl UpdateName {
/// Constructs an [`UpdateName`], after verifying that an update sequence ID
Expand All@@ -931,13 +1009,40 @@ impl UpdateName {
}
}

/// Convert this monitor update name to a &str
/// Convert this update name to a string slice.
///
/// This method is particularly useful when you need to use the update name
/// as part of a key in a key-value store or when logging.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_name = UpdateName::from(42);
/// assert_eq!(update_name.as_str(), "42");
/// ```
pub fn as_str(&self) -> &str {
&self.1
}
}

impl From<u64> for UpdateName {
/// Creates an `UpdateName` from a `u64`.
///
/// This is typically used when you need to generate a storage key or
/// identifier
/// for a new channel monitor update.
///
/// # Examples
///
/// ```
/// use lightning::util::persist::UpdateName;
///
/// let update_id: u64 = 42;
/// let update_name = UpdateName::from(update_id);
/// assert_eq!(update_name.as_str(), "42");
/// ```
fn from(value: u64) -> Self {
Self(value, value.to_string())
}
Expand Down