breez_sdk_liquid::lightning::util::persist

Struct MonitorUpdatingPersister

pub struct MonitorUpdatingPersister<K, L, ES, SP>
where K: Deref, L: Deref, ES: Deref, SP: Deref, <K as Deref>::Target: KVStore, <L as Deref>::Target: Logger, <ES as Deref>::Target: Sized + EntropySource, <SP as Deref>::Target: Sized + SignerProvider,
{ /* private fields */ }
Expand description

Implements Persist in a way that writes and reads both ChannelMonitors and ChannelMonitorUpdates.

§Overview

The main benefit this provides over the KVStore’s Persist implementation is decreased I/O bandwidth and storage churn, at the expense of more IOPS (including listing, reading, and deleting) and complexity. This is because it writes channel monitor differential updates, whereas the other (default) implementation rewrites the entire monitor on each update. For routing nodes, updates can happen many times per second to a channel, and monitors can be tens of megabytes (or more). Updates can be as small as a few hundred bytes.

Note that monitors written with MonitorUpdatingPersister are not backward-compatible with the default KVStore’s Persist implementation. They have a prepended byte sequence, MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL, applied to prevent deserialization with other persisters. This is because monitors written by this struct may have unapplied updates. In order to downgrade, you must ensure that all updates are applied to the monitor, and remove the sentinel bytes.

§Storing monitors

Monitors are stored by implementing the Persist trait, which has two functions:

Whole ChannelMonitors are stored in the CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, using the familiar encoding of an OutPoint (for example, [SOME-64-CHAR-HEX-STRING]_1).

Each ChannelMonitorUpdate is stored in a dynamic secondary namespace, as follows:

Under that secondary namespace, each update is stored with a number string, like 21, which represents its update_id value.

For example, consider this channel, named for its transaction ID and index, or OutPoint:

  • Transaction ID: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
  • Index: 1

Full channel monitors would be stored at a single key:

[CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE]/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1

Updates would be stored as follows (with / delimiting primary_namespace/secondary_namespace/key):

[CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE]/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1/1
[CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE]/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1/2
[CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE]/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1/3

… and so on.

§Reading channel state from storage

Channel state can be reconstructed by calling MonitorUpdatingPersister::read_all_channel_monitors_with_updates. Alternatively, users can list channel monitors themselves and load channels individually using MonitorUpdatingPersister::read_channel_monitor_with_updates.

§EXTREMELY IMPORTANT

It is extremely important that your KVStore::read implementation uses the io::ErrorKind::NotFound variant correctly: that is, when a file is not found, and only in that circumstance (not when there is really a permissions error, for example). This is because neither channel monitor reading function lists updates. Instead, either reads the monitor, and using its stored update_id, synthesizes update storage keys, and tries them in sequence until one is not found. All other errors will be bubbled up in the function’s Result.

§Pruning stale channel updates

Stale updates are pruned when a full monitor is written. The old monitor is first read, and if that succeeds, updates in the range between the old and new monitors are deleted. The lazy flag is used on the KVStore::remove method, so there are no guarantees that the deletions will complete. However, stale updates are not a problem for data integrity, since updates are only read that are higher than the stored ChannelMonitor’s update_id.

If you have many stale updates stored (such as after a crash with pending lazy deletes), and would like to get rid of them, consider using the MonitorUpdatingPersister::cleanup_stale_updates function.

Implementations§

§

impl<K, L, ES, SP> MonitorUpdatingPersister<K, L, ES, SP>
where K: Deref, L: Deref, ES: Deref, SP: Deref, <K as Deref>::Target: KVStore, <L as Deref>::Target: Logger, <ES as Deref>::Target: Sized + EntropySource, <SP as Deref>::Target: Sized + SignerProvider,

pub fn new( kv_store: K, logger: L, maximum_pending_updates: u64, entropy_source: ES, signer_provider: SP, ) -> MonitorUpdatingPersister<K, L, ES, SP>

Constructs a new MonitorUpdatingPersister.

The maximum_pending_updates parameter controls how many updates may be stored before a MonitorUpdatingPersister consolidates updates by writing a full monitor. Note that consolidation will frequently occur with fewer updates than what you set here; this number is merely the maximum that may be stored. When setting this value, consider that for higher values of maximum_pending_updates:

pub fn read_all_channel_monitors_with_updates<B, F>( &self, broadcaster: &B, fee_estimator: &F, ) -> Result<Vec<(BlockHash, ChannelMonitor<<<SP as Deref>::Target as SignerProvider>::Signer>)>, Error>

Reads all stored channel monitors, along with any stored updates for them.

It is extremely important that your KVStore::read implementation uses the io::ErrorKind::NotFound variant correctly. For more information, please see the documentation for MonitorUpdatingPersister.

pub fn read_channel_monitor_with_updates<B, F>( &self, broadcaster: &B, fee_estimator: &F, monitor_key: String, ) -> Result<(BlockHash, ChannelMonitor<<<SP as Deref>::Target as SignerProvider>::Signer>), Error>

Read a single channel monitor, along with any stored updates for it.

It is extremely important that your KVStore::read implementation uses the io::ErrorKind::NotFound variant correctly. For more information, please see the documentation for MonitorUpdatingPersister.

For monitor_key, channel storage keys be the channel’s transaction ID and index, or OutPoint, with an underscore _ between them. For example, given:

  • Transaction ID: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
  • Index: 1

The correct monitor_key would be: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1

Loading a large number of monitors will be faster if done in parallel. You can use this function to accomplish this. Take care to limit the number of parallel readers.

pub fn cleanup_stale_updates(&self, lazy: bool) -> Result<(), Error>

Cleans up stale updates for all monitors.

This function works by first listing all monitors, and then for each of them, listing all updates. The updates that have an update_id less than or equal to than the stored monitor are deleted. The deletion can either be lazy or non-lazy based on the lazy flag; this will be passed to KVStore::remove.

Trait Implementations§

§

impl<ChannelSigner, K, L, ES, SP> Persist<ChannelSigner> for MonitorUpdatingPersister<K, L, ES, SP>
where ChannelSigner: WriteableEcdsaChannelSigner, K: Deref, L: Deref, ES: Deref, SP: Deref, <K as Deref>::Target: KVStore, <L as Deref>::Target: Logger, <ES as Deref>::Target: Sized + EntropySource, <SP as Deref>::Target: Sized + SignerProvider,

§

fn persist_new_channel( &self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>, _monitor_update_call_id: MonitorUpdateId, ) -> ChannelMonitorUpdateStatus

Persists a new channel. This means writing the entire monitor to the parametrized KVStore.

§

fn update_persisted_channel( &self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>, monitor_update_call_id: MonitorUpdateId, ) -> ChannelMonitorUpdateStatus

Persists a channel update, writing only the update to the parameterized KVStore if possible.

In some cases, this will forward to MonitorUpdatingPersister::persist_new_channel:

  • 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.
  • The update is at CLOSED_CHANNEL_UPDATE_ID

Auto Trait Implementations§

§

impl<K, L, ES, SP> Freeze for MonitorUpdatingPersister<K, L, ES, SP>
where <SP as Deref>::Target: Sized, <ES as Deref>::Target: Sized, K: Freeze, L: Freeze, ES: Freeze, SP: Freeze,

§

impl<K, L, ES, SP> RefUnwindSafe for MonitorUpdatingPersister<K, L, ES, SP>

§

impl<K, L, ES, SP> Send for MonitorUpdatingPersister<K, L, ES, SP>
where <SP as Deref>::Target: Sized, <ES as Deref>::Target: Sized, K: Send, L: Send, ES: Send, SP: Send,

§

impl<K, L, ES, SP> Sync for MonitorUpdatingPersister<K, L, ES, SP>
where <SP as Deref>::Target: Sized, <ES as Deref>::Target: Sized, K: Sync, L: Sync, ES: Sync, SP: Sync,

§

impl<K, L, ES, SP> Unpin for MonitorUpdatingPersister<K, L, ES, SP>
where <SP as Deref>::Target: Sized, <ES as Deref>::Target: Sized, K: Unpin, L: Unpin, ES: Unpin, SP: Unpin,

§

impl<K, L, ES, SP> UnwindSafe for MonitorUpdatingPersister<K, L, ES, SP>
where <SP as Deref>::Target: Sized, <ES as Deref>::Target: Sized, K: UnwindSafe, L: UnwindSafe, ES: UnwindSafe, SP: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> DartSafe for T

§

impl<T> TaskRetFutTrait for T
where T: Send,