From: Valentine Wallace Date: Wed, 16 Sep 2020 21:43:33 +0000 (-0400) Subject: Add Persist trait. X-Git-Tag: v0.0.12~10^2~5 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=ec4715c09b41b4d9c3098538c04c6ca3ee4f2691;p=rust-lightning Add Persist trait. Implementors of Persist are responsible for persisting new ChannelMonitors and ChannelMonitor updates to disk/backups. --- diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 315b2afec..93a4edb6e 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -2123,6 +2123,61 @@ impl ChannelMonitor { } } +/// `Persist` defines behavior for persisting channel monitors: this could mean +/// writing once to disk, and/or uploading to one or more backup services. +/// +/// Note that for every new monitor, you **must** persist the new `ChannelMonitor` +/// to disk/backups. And, on every update, you **must** persist either the +/// `ChannelMonitorUpdate` or the updated monitor itself. Otherwise, there is risk +/// of situations such as revoking a transaction, then crashing before this +/// revocation can be persisted, then unintentionally broadcasting a revoked +/// transaction and losing money. This is a risk because previous channel states +/// are toxic, so it's important that whatever channel state is persisted is +/// kept up-to-date. +pub trait Persist: Send + Sync { + /// Persist a new channel's data. The data can be stored any way you want, but + /// the identifier provided by Rust-Lightning is the channel's outpoint (and + /// it is up to you to maintain a correct mapping between the outpoint and the + /// stored channel data). Note that you **must** persist every new monitor to + /// disk. See the `Persist` trait documentation for more details. + /// + /// See [`ChannelMonitor::write_for_disk`] for writing out a `ChannelMonitor`, + /// and [`ChannelMonitorUpdateErr`] for requirements when returning errors. + /// + /// [`ChannelMonitor::write_for_disk`]: struct.ChannelMonitor.html#method.write_for_disk + /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + fn persist_new_channel(&self, id: OutPoint, data: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; + + /// Update one channel's data. The provided `ChannelMonitor` has already + /// applied the given update. + /// + /// Note that on every update, you **must** persist either the + /// `ChannelMonitorUpdate` or the updated monitor itself to disk/backups. See + /// the `Persist` trait documentation for more details. + /// + /// If an implementer chooses to persist the updates only, they need to make + /// sure that all the updates are applied to the `ChannelMonitors` *before* + /// the set of channel monitors is given to the `ChannelManager` + /// deserialization routine. See [`ChannelMonitor::update_monitor`] for + /// applying a monitor update to a monitor. If full `ChannelMonitors` are + /// persisted, then there is no need to persist individual updates. + /// + /// Note that there could be a performance tradeoff between persisting complete + /// channel monitors on every update vs. persisting only updates and applying + /// them in batches. The size of each monitor grows `O(number of state updates)` + /// whereas updates are small and `O(1)`. + /// + /// See [`ChannelMonitor::write_for_disk`] for writing out a `ChannelMonitor`, + /// [`ChannelMonitorUpdate::write`] for writing out an update, and + /// [`ChannelMonitorUpdateErr`] for requirements when returning errors. + /// + /// [`ChannelMonitor::update_monitor`]: struct.ChannelMonitor.html#impl-1 + /// [`ChannelMonitor::write_for_disk`]: struct.ChannelMonitor.html#method.write_for_disk + /// [`ChannelMonitorUpdate::write`]: struct.ChannelMonitorUpdate.html#method.write + /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + fn update_persisted_channel(&self, id: OutPoint, update: &ChannelMonitorUpdate, data: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; +} + const MAX_ALLOC_SIZE: usize = 64*1024; impl Readable for (BlockHash, ChannelMonitor) {