X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=ldk-c-bindings;a=blobdiff_plain;f=lightning-c-bindings%2Fsrc%2Flightning%2Fchain%2Fmod.rs;fp=lightning-c-bindings%2Fsrc%2Flightning%2Fchain%2Fmod.rs;h=fb9794fab8883aa76559703817abacb325f5c227;hp=5ab4d47cdeaabd1344e3ff2e692da94efce0805a;hb=c809fde8131b3ffdb6e5c73709e85d918a87c87d;hpb=7d8ba6706e4a52744eeab9590fa1bfea1a6fc211 diff --git a/lightning-c-bindings/src/lightning/chain/mod.rs b/lightning-c-bindings/src/lightning/chain/mod.rs index 5ab4d47..fb9794f 100644 --- a/lightning-c-bindings/src/lightning/chain/mod.rs +++ b/lightning-c-bindings/src/lightning/chain/mod.rs @@ -113,6 +113,15 @@ pub(crate) extern "C" fn BestBlock_clone_void(this_ptr: *const c_void) -> *mut c pub extern "C" fn BestBlock_clone(orig: &BestBlock) -> BestBlock { orig.clone() } +/// Checks if two BestBlocks contain equal inner contents. +/// This ignores pointers and is_owned flags and looks at the values in fields. +/// Two objects with NULL inner values will be considered "equal" here. +#[no_mangle] +pub extern "C" fn BestBlock_eq(a: &BestBlock, b: &BestBlock) -> bool { + if a.inner == b.inner { return true; } + if a.inner.is_null() || b.inner.is_null() { return false; } + if a.get_native_ref() == b.get_native_ref() { true } else { false } +} /// Constructs a `BestBlock` that represents the genesis block at height 0 of the given /// network. #[must_use] @@ -470,118 +479,145 @@ impl Drop for Confirm { } } } -/// An error enum representing a failure to persist a channel monitor update. +/// An enum representing the status of a channel monitor update persistence. #[derive(Clone)] #[must_use] #[repr(C)] -pub enum ChannelMonitorUpdateErr { +pub enum ChannelMonitorUpdateStatus { + /// The update has been durably persisted and all copies of the relevant [`ChannelMonitor`] + /// have been updated. + /// + /// This includes performing any `fsync()` calls required to ensure the update is guaranteed to + /// be available on restart even if the application crashes. + Completed, /// Used to indicate a temporary failure (eg connection to a watchtower or remote backup of /// our state failed, but is expected to succeed at some point in the future). /// /// Such a failure will \"freeze\" a channel, preventing us from revoking old states or - /// submitting new commitment transactions to the counterparty. Once the update(s) that failed - /// have been successfully applied, a [`MonitorEvent::UpdateCompleted`] event should be returned - /// via [`Watch::release_pending_monitor_events`] which will then restore the channel to an - /// operational state. - /// - /// Note that a given ChannelManager will *never* re-generate a given ChannelMonitorUpdate. If - /// you return a TemporaryFailure you must ensure that it is written to disk safely before - /// writing out the latest ChannelManager state. - /// - /// Even when a channel has been \"frozen\" updates to the ChannelMonitor can continue to occur - /// (eg if an inbound HTLC which we forwarded was claimed upstream resulting in us attempting - /// to claim it on this channel) and those updates must be applied wherever they can be. At - /// least one such updated ChannelMonitor must be persisted otherwise PermanentFailure should - /// be returned to get things on-chain ASAP using only the in-memory copy. Obviously updates to - /// the channel which would invalidate previous ChannelMonitors are not made when a channel has - /// been \"frozen\". - /// - /// Note that even if updates made after TemporaryFailure succeed you must still provide a - /// [`MonitorEvent::UpdateCompleted`] to ensure you have the latest monitor and re-enable - /// normal channel operation. Note that this is normally generated through a call to - /// [`ChainMonitor::channel_monitor_updated`]. - /// - /// Note that the update being processed here will not be replayed for you when you return a - /// [`MonitorEvent::UpdateCompleted`] event via [`Watch::release_pending_monitor_events`], so - /// you must store the update itself on your own local disk prior to returning a - /// TemporaryFailure. You may, of course, employ a journaling approach, storing only the - /// ChannelMonitorUpdate on disk without updating the monitor itself, replaying the journal at - /// reload-time. + /// submitting new commitment transactions to the counterparty. Once the update(s) which failed + /// have been successfully applied, a [`MonitorEvent::Completed`] can be used to restore the + /// channel to an operational state. + /// + /// Note that a given [`ChannelManager`] will *never* re-generate a [`ChannelMonitorUpdate`]. + /// If you return this error you must ensure that it is written to disk safely before writing + /// the latest [`ChannelManager`] state, or you should return [`PermanentFailure`] instead. + /// + /// Even when a channel has been \"frozen\", updates to the [`ChannelMonitor`] can continue to + /// occur (e.g. if an inbound HTLC which we forwarded was claimed upstream, resulting in us + /// attempting to claim it on this channel) and those updates must still be persisted. + /// + /// No updates to the channel will be made which could invalidate other [`ChannelMonitor`]s + /// until a [`MonitorEvent::Completed`] is provided, even if you return no error on a later + /// monitor update for the same channel. /// /// For deployments where a copy of ChannelMonitors and other local state are backed up in a /// remote location (with local copies persisted immediately), it is anticipated that all - /// updates will return TemporaryFailure until the remote copies could be updated. + /// updates will return [`InProgress`] until the remote copies could be updated. + /// + /// [`PermanentFailure`]: ChannelMonitorUpdateStatus::PermanentFailure + /// [`InProgress`]: ChannelMonitorUpdateStatus::InProgress + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager + InProgress, + /// Used to indicate no further channel monitor updates will be allowed (likely a disk failure + /// or a remote copy of this [`ChannelMonitor`] is no longer reachable and thus not updatable). /// - /// [`ChainMonitor::channel_monitor_updated`]: chainmonitor::ChainMonitor::channel_monitor_updated - TemporaryFailure, - /// Used to indicate no further channel monitor updates will be allowed (eg we've moved on to a - /// different watchtower and cannot update with all watchtowers that were previously informed - /// of this channel). + /// When this is returned, [`ChannelManager`] will force-close the channel but *not* broadcast + /// our current commitment transaction. This avoids a dangerous case where a local disk failure + /// (e.g. the Linux-default remounting of the disk as read-only) causes [`PermanentFailure`]s + /// for all monitor updates. If we were to broadcast our latest commitment transaction and then + /// restart, we could end up reading a previous [`ChannelMonitor`] and [`ChannelManager`], + /// revoking our now-broadcasted state before seeing it confirm and losing all our funds. /// - /// At reception of this error, ChannelManager will force-close the channel and return at - /// least a final ChannelMonitorUpdate::ChannelForceClosed which must be delivered to at - /// least one ChannelMonitor copy. Revocation secret MUST NOT be released and offchain channel - /// update must be rejected. + /// Note that this is somewhat of a tradeoff - if the disk is really gone and we may have lost + /// the data permanently, we really should broadcast immediately. If the data can be recovered + /// with manual intervention, we'd rather close the channel, rejecting future updates to it, + /// and broadcast the latest state only if we have HTLCs to claim which are timing out (which + /// we do as long as blocks are connected). /// - /// This failure may also signal a failure to update the local persisted copy of one of - /// the channel monitor instance. + /// In order to broadcast the latest local commitment transaction, you'll need to call + /// [`ChannelMonitor::get_latest_holder_commitment_txn`] and broadcast the resulting + /// transactions once you've safely ensured no further channel updates can be generated by your + /// [`ChannelManager`]. /// - /// Note that even when you fail a holder commitment transaction update, you must store the - /// update to ensure you can claim from it in case of a duplicate copy of this ChannelMonitor - /// broadcasts it (e.g distributed channel-monitor deployment) + /// Note that at least one final [`ChannelMonitorUpdate`] may still be provided, which must + /// still be processed by a running [`ChannelMonitor`]. This final update will mark the + /// [`ChannelMonitor`] as finalized, ensuring no further updates (e.g. revocation of the latest + /// commitment transaction) are allowed. + /// + /// Note that even if you return a [`PermanentFailure`] due to unavailability of secondary + /// [`ChannelMonitor`] copies, you should still make an attempt to store the update where + /// possible to ensure you can claim HTLC outputs on the latest commitment transaction + /// broadcasted later. /// /// In case of distributed watchtowers deployment, the new version must be written to disk, as /// state may have been stored but rejected due to a block forcing a commitment broadcast. This /// storage is used to claim outputs of rejected state confirmed onchain by another watchtower, /// lagging behind on block processing. + /// + /// [`PermanentFailure`]: ChannelMonitorUpdateStatus::PermanentFailure + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager PermanentFailure, } -use lightning::chain::ChannelMonitorUpdateErr as ChannelMonitorUpdateErrImport; -pub(crate) type nativeChannelMonitorUpdateErr = ChannelMonitorUpdateErrImport; +use lightning::chain::ChannelMonitorUpdateStatus as ChannelMonitorUpdateStatusImport; +pub(crate) type nativeChannelMonitorUpdateStatus = ChannelMonitorUpdateStatusImport; -impl ChannelMonitorUpdateErr { +impl ChannelMonitorUpdateStatus { #[allow(unused)] - pub(crate) fn to_native(&self) -> nativeChannelMonitorUpdateErr { + pub(crate) fn to_native(&self) -> nativeChannelMonitorUpdateStatus { match self { - ChannelMonitorUpdateErr::TemporaryFailure => nativeChannelMonitorUpdateErr::TemporaryFailure, - ChannelMonitorUpdateErr::PermanentFailure => nativeChannelMonitorUpdateErr::PermanentFailure, + ChannelMonitorUpdateStatus::Completed => nativeChannelMonitorUpdateStatus::Completed, + ChannelMonitorUpdateStatus::InProgress => nativeChannelMonitorUpdateStatus::InProgress, + ChannelMonitorUpdateStatus::PermanentFailure => nativeChannelMonitorUpdateStatus::PermanentFailure, } } #[allow(unused)] - pub(crate) fn into_native(self) -> nativeChannelMonitorUpdateErr { + pub(crate) fn into_native(self) -> nativeChannelMonitorUpdateStatus { match self { - ChannelMonitorUpdateErr::TemporaryFailure => nativeChannelMonitorUpdateErr::TemporaryFailure, - ChannelMonitorUpdateErr::PermanentFailure => nativeChannelMonitorUpdateErr::PermanentFailure, + ChannelMonitorUpdateStatus::Completed => nativeChannelMonitorUpdateStatus::Completed, + ChannelMonitorUpdateStatus::InProgress => nativeChannelMonitorUpdateStatus::InProgress, + ChannelMonitorUpdateStatus::PermanentFailure => nativeChannelMonitorUpdateStatus::PermanentFailure, } } #[allow(unused)] - pub(crate) fn from_native(native: &nativeChannelMonitorUpdateErr) -> Self { + pub(crate) fn from_native(native: &nativeChannelMonitorUpdateStatus) -> Self { match native { - nativeChannelMonitorUpdateErr::TemporaryFailure => ChannelMonitorUpdateErr::TemporaryFailure, - nativeChannelMonitorUpdateErr::PermanentFailure => ChannelMonitorUpdateErr::PermanentFailure, + nativeChannelMonitorUpdateStatus::Completed => ChannelMonitorUpdateStatus::Completed, + nativeChannelMonitorUpdateStatus::InProgress => ChannelMonitorUpdateStatus::InProgress, + nativeChannelMonitorUpdateStatus::PermanentFailure => ChannelMonitorUpdateStatus::PermanentFailure, } } #[allow(unused)] - pub(crate) fn native_into(native: nativeChannelMonitorUpdateErr) -> Self { + pub(crate) fn native_into(native: nativeChannelMonitorUpdateStatus) -> Self { match native { - nativeChannelMonitorUpdateErr::TemporaryFailure => ChannelMonitorUpdateErr::TemporaryFailure, - nativeChannelMonitorUpdateErr::PermanentFailure => ChannelMonitorUpdateErr::PermanentFailure, + nativeChannelMonitorUpdateStatus::Completed => ChannelMonitorUpdateStatus::Completed, + nativeChannelMonitorUpdateStatus::InProgress => ChannelMonitorUpdateStatus::InProgress, + nativeChannelMonitorUpdateStatus::PermanentFailure => ChannelMonitorUpdateStatus::PermanentFailure, } } } -/// Creates a copy of the ChannelMonitorUpdateErr +/// Creates a copy of the ChannelMonitorUpdateStatus #[no_mangle] -pub extern "C" fn ChannelMonitorUpdateErr_clone(orig: &ChannelMonitorUpdateErr) -> ChannelMonitorUpdateErr { +pub extern "C" fn ChannelMonitorUpdateStatus_clone(orig: &ChannelMonitorUpdateStatus) -> ChannelMonitorUpdateStatus { orig.clone() } #[no_mangle] -/// Utility method to constructs a new TemporaryFailure-variant ChannelMonitorUpdateErr -pub extern "C" fn ChannelMonitorUpdateErr_temporary_failure() -> ChannelMonitorUpdateErr { - ChannelMonitorUpdateErr::TemporaryFailure} +/// Utility method to constructs a new Completed-variant ChannelMonitorUpdateStatus +pub extern "C" fn ChannelMonitorUpdateStatus_completed() -> ChannelMonitorUpdateStatus { + ChannelMonitorUpdateStatus::Completed} #[no_mangle] -/// Utility method to constructs a new PermanentFailure-variant ChannelMonitorUpdateErr -pub extern "C" fn ChannelMonitorUpdateErr_permanent_failure() -> ChannelMonitorUpdateErr { - ChannelMonitorUpdateErr::PermanentFailure} +/// Utility method to constructs a new InProgress-variant ChannelMonitorUpdateStatus +pub extern "C" fn ChannelMonitorUpdateStatus_in_progress() -> ChannelMonitorUpdateStatus { + ChannelMonitorUpdateStatus::InProgress} +#[no_mangle] +/// Utility method to constructs a new PermanentFailure-variant ChannelMonitorUpdateStatus +pub extern "C" fn ChannelMonitorUpdateStatus_permanent_failure() -> ChannelMonitorUpdateStatus { + ChannelMonitorUpdateStatus::PermanentFailure} +/// Checks if two ChannelMonitorUpdateStatuss contain equal inner contents. +/// This ignores pointers and is_owned flags and looks at the values in fields. +#[no_mangle] +pub extern "C" fn ChannelMonitorUpdateStatus_eq(a: &ChannelMonitorUpdateStatus, b: &ChannelMonitorUpdateStatus) -> bool { + if &a.to_native() == &b.to_native() { true } else { false } +} /// The `Watch` trait defines behavior for watching on-chain activity pertaining to channels as /// blocks are connected and disconnected. /// @@ -597,10 +633,10 @@ pub extern "C" fn ChannelMonitorUpdateErr_permanent_failure() -> ChannelMonitorU /// If an implementation maintains multiple instances of a channel's monitor (e.g., by storing /// backup copies), then it must ensure that updates are applied across all instances. Otherwise, it /// could result in a revoked transaction being broadcast, allowing the counterparty to claim all -/// funds in the channel. See [`ChannelMonitorUpdateErr`] for more details about how to handle +/// funds in the channel. See [`ChannelMonitorUpdateStatus`] for more details about how to handle /// multiple instances. /// -/// [`PermanentFailure`]: ChannelMonitorUpdateErr::PermanentFailure +/// [`PermanentFailure`]: ChannelMonitorUpdateStatus::PermanentFailure #[repr(C)] pub struct Watch { /// An opaque pointer which is passed to your function implementations as an argument. @@ -612,22 +648,22 @@ pub struct Watch { /// with any spends of outputs returned by [`get_outputs_to_watch`]. In practice, this means /// calling [`block_connected`] and [`block_disconnected`] on the monitor. /// - /// Note: this interface MUST error with `ChannelMonitorUpdateErr::PermanentFailure` if + /// Note: this interface MUST error with [`ChannelMonitorUpdateStatus::PermanentFailure`] if /// the given `funding_txo` has previously been registered via `watch_channel`. /// /// [`get_outputs_to_watch`]: channelmonitor::ChannelMonitor::get_outputs_to_watch /// [`block_connected`]: channelmonitor::ChannelMonitor::block_connected /// [`block_disconnected`]: channelmonitor::ChannelMonitor::block_disconnected #[must_use] - pub watch_channel: extern "C" fn (this_arg: *const c_void, funding_txo: crate::lightning::chain::transaction::OutPoint, monitor: crate::lightning::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ, + pub watch_channel: extern "C" fn (this_arg: *const c_void, funding_txo: crate::lightning::chain::transaction::OutPoint, monitor: crate::lightning::chain::channelmonitor::ChannelMonitor) -> crate::lightning::chain::ChannelMonitorUpdateStatus, /// Updates a channel identified by `funding_txo` by applying `update` to its monitor. /// /// Implementations must call [`update_monitor`] with the given update. See - /// [`ChannelMonitorUpdateErr`] for invariants around returning an error. + /// [`ChannelMonitorUpdateStatus`] for invariants around returning an error. /// /// [`update_monitor`]: channelmonitor::ChannelMonitor::update_monitor #[must_use] - pub update_channel: extern "C" fn (this_arg: *const c_void, funding_txo: crate::lightning::chain::transaction::OutPoint, update: crate::lightning::chain::channelmonitor::ChannelMonitorUpdate) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ, + pub update_channel: extern "C" fn (this_arg: *const c_void, funding_txo: crate::lightning::chain::transaction::OutPoint, update: crate::lightning::chain::channelmonitor::ChannelMonitorUpdate) -> crate::lightning::chain::ChannelMonitorUpdateStatus, /// Returns any monitor events since the last call. Subsequent calls must only return new /// events. /// @@ -636,7 +672,7 @@ pub struct Watch { /// to disk. /// /// For details on asynchronous [`ChannelMonitor`] updating and returning - /// [`MonitorEvent::UpdateCompleted`] here, see [`ChannelMonitorUpdateErr::TemporaryFailure`]. + /// [`MonitorEvent::Completed`] here, see [`ChannelMonitorUpdateStatus::InProgress`]. #[must_use] pub release_pending_monitor_events: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_C3Tuple_OutPointCVec_MonitorEventZPublicKeyZZ, /// Frees any resources associated with this object given its this_arg pointer. @@ -658,15 +694,13 @@ pub(crate) extern "C" fn Watch_clone_fields(orig: &Watch) -> Watch { use lightning::chain::Watch as rustWatch; impl rustWatch for Watch { - fn watch_channel(&self, mut funding_txo: lightning::chain::transaction::OutPoint, mut monitor: lightning::chain::channelmonitor::ChannelMonitor) -> Result<(), lightning::chain::ChannelMonitorUpdateErr> { + fn watch_channel(&self, mut funding_txo: lightning::chain::transaction::OutPoint, mut monitor: lightning::chain::channelmonitor::ChannelMonitor) -> lightning::chain::ChannelMonitorUpdateStatus { let mut ret = (self.watch_channel)(self.this_arg, crate::lightning::chain::transaction::OutPoint { inner: ObjOps::heap_alloc(funding_txo), is_owned: true }, crate::lightning::chain::channelmonitor::ChannelMonitor { inner: ObjOps::heap_alloc(monitor), is_owned: true }); - let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.result)) })*/ }), false => Err( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) }).into_native() })}; - local_ret + ret.into_native() } - fn update_channel(&self, mut funding_txo: lightning::chain::transaction::OutPoint, mut update: lightning::chain::channelmonitor::ChannelMonitorUpdate) -> Result<(), lightning::chain::ChannelMonitorUpdateErr> { + fn update_channel(&self, mut funding_txo: lightning::chain::transaction::OutPoint, mut update: lightning::chain::channelmonitor::ChannelMonitorUpdate) -> lightning::chain::ChannelMonitorUpdateStatus { let mut ret = (self.update_channel)(self.this_arg, crate::lightning::chain::transaction::OutPoint { inner: ObjOps::heap_alloc(funding_txo), is_owned: true }, crate::lightning::chain::channelmonitor::ChannelMonitorUpdate { inner: ObjOps::heap_alloc(update), is_owned: true }); - let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.result)) })*/ }), false => Err( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) }).into_native() })}; - local_ret + ret.into_native() } fn release_pending_monitor_events(&self) -> Vec<(lightning::chain::transaction::OutPoint, Vec, Option)> { let mut ret = (self.release_pending_monitor_events)(self.this_arg); @@ -708,9 +742,9 @@ impl Drop for Watch { /// Note that use as part of a [`Watch`] implementation involves reentrancy. Therefore, the `Filter` /// should not block on I/O. Implementations should instead queue the newly monitored data to be /// processed later. Then, in order to block until the data has been processed, any [`Watch`] -/// invocation that has called the `Filter` must return [`TemporaryFailure`]. +/// invocation that has called the `Filter` must return [`InProgress`]. /// -/// [`TemporaryFailure`]: ChannelMonitorUpdateErr::TemporaryFailure +/// [`InProgress`]: ChannelMonitorUpdateStatus::InProgress /// [BIP 157]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki /// [BIP 158]: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki #[repr(C)] @@ -903,6 +937,15 @@ pub extern "C" fn WatchedOutput_clone(orig: &WatchedOutput) -> WatchedOutput { orig.clone() } /// Checks if two WatchedOutputs contain equal inner contents. +/// This ignores pointers and is_owned flags and looks at the values in fields. +/// Two objects with NULL inner values will be considered "equal" here. +#[no_mangle] +pub extern "C" fn WatchedOutput_eq(a: &WatchedOutput, b: &WatchedOutput) -> bool { + if a.inner == b.inner { return true; } + if a.inner.is_null() || b.inner.is_null() { return false; } + if a.get_native_ref() == b.get_native_ref() { true } else { false } +} +/// Checks if two WatchedOutputs contain equal inner contents. #[no_mangle] pub extern "C" fn WatchedOutput_hash(o: &WatchedOutput) -> u64 { if o.inner.is_null() { return 0; }