X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-c-bindings%2Fsrc%2Fln%2Fchannelmanager.rs;h=3b2ca23e85f5197406eb981b25710933625bb463;hb=7e0d8189ef1fab54216e446938ac473588bf21cb;hp=2ab0c9fb7640383ffb79fd5259b5d46b48da3e84;hpb=8050269803d4b7bd9079e1887000b9807d14bcf1;p=ldk-c-bindings diff --git a/lightning-c-bindings/src/ln/channelmanager.rs b/lightning-c-bindings/src/ln/channelmanager.rs index 2ab0c9f..3b2ca23 100644 --- a/lightning-c-bindings/src/ln/channelmanager.rs +++ b/lightning-c-bindings/src/ln/channelmanager.rs @@ -54,7 +54,7 @@ type nativeChannelManager = nativeChannelManagerImport cra pub extern "C" fn ChainParameters_set_network(this_ptr: &mut ChainParameters, mut val: crate::bitcoin::network::Network) { unsafe { &mut *this_ptr.inner }.network = val.into_bitcoin(); } -/// The hash of the latest block successfully connected. -#[no_mangle] -pub extern "C" fn ChainParameters_get_latest_hash(this_ptr: &ChainParameters) -> *const [u8; 32] { - let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.latest_hash; - (*inner_val).as_inner() -} -/// The hash of the latest block successfully connected. -#[no_mangle] -pub extern "C" fn ChainParameters_set_latest_hash(this_ptr: &mut ChainParameters, mut val: crate::c_types::ThirtyTwoBytes) { - unsafe { &mut *this_ptr.inner }.latest_hash = ::bitcoin::hash_types::BlockHash::from_slice(&val.data[..]).unwrap(); -} -/// The height of the latest block successfully connected. +/// The hash and height of the latest block successfully connected. /// /// Used to track on-chain channel funding outputs and send payments with reliable timelocks. #[no_mangle] -pub extern "C" fn ChainParameters_get_latest_height(this_ptr: &ChainParameters) -> usize { - let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.latest_height; - (*inner_val) +pub extern "C" fn ChainParameters_get_best_block(this_ptr: &ChainParameters) -> crate::ln::channelmanager::BestBlock { + let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.best_block; + crate::ln::channelmanager::BestBlock { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false } } -/// The height of the latest block successfully connected. +/// The hash and height of the latest block successfully connected. /// /// Used to track on-chain channel funding outputs and send payments with reliable timelocks. #[no_mangle] -pub extern "C" fn ChainParameters_set_latest_height(this_ptr: &mut ChainParameters, mut val: usize) { - unsafe { &mut *this_ptr.inner }.latest_height = val; +pub extern "C" fn ChainParameters_set_best_block(this_ptr: &mut ChainParameters, mut val: crate::ln::channelmanager::BestBlock) { + unsafe { &mut *this_ptr.inner }.best_block = *unsafe { Box::from_raw(val.take_inner()) }; } /// Constructs a new ChainParameters given each field #[must_use] #[no_mangle] -pub extern "C" fn ChainParameters_new(mut network_arg: crate::bitcoin::network::Network, mut latest_hash_arg: crate::c_types::ThirtyTwoBytes, mut latest_height_arg: usize) -> ChainParameters { +pub extern "C" fn ChainParameters_new(mut network_arg: crate::bitcoin::network::Network, mut best_block_arg: crate::ln::channelmanager::BestBlock) -> ChainParameters { ChainParameters { inner: Box::into_raw(Box::new(nativeChainParameters { network: network_arg.into_bitcoin(), - latest_hash: ::bitcoin::hash_types::BlockHash::from_slice(&latest_hash_arg.data[..]).unwrap(), - latest_height: latest_height_arg, + best_block: *unsafe { Box::from_raw(best_block_arg.take_inner()) }, })), is_owned: true } } + +use lightning::ln::channelmanager::BestBlock as nativeBestBlockImport; +type nativeBestBlock = nativeBestBlockImport; + +/// The best known block as identified by its hash and height. +#[must_use] +#[repr(C)] +pub struct BestBlock { + /// A pointer to the opaque Rust object. + + /// Nearly everywhere, inner must be non-null, however in places where + /// the Rust equivalent takes an Option, it may be set to null to indicate None. + pub inner: *mut nativeBestBlock, + /// Indicates that this is the only struct which contains the same pointer. + + /// Rust functions which take ownership of an object provided via an argument require + /// this to be true and invalidate the object pointed to by inner. + pub is_owned: bool, +} + +impl Drop for BestBlock { + fn drop(&mut self) { + if self.is_owned && !<*mut nativeBestBlock>::is_null(self.inner) { + let _ = unsafe { Box::from_raw(self.inner) }; + } + } +} +/// Frees any resources used by the BestBlock, if is_owned is set and inner is non-NULL. +#[no_mangle] +pub extern "C" fn BestBlock_free(this_obj: BestBlock) { } +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +extern "C" fn BestBlock_free_void(this_ptr: *mut c_void) { + unsafe { let _ = Box::from_raw(this_ptr as *mut nativeBestBlock); } +} +#[allow(unused)] +/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy +impl BestBlock { + pub(crate) fn take_inner(mut self) -> *mut nativeBestBlock { + assert!(self.is_owned); + let ret = self.inner; + self.inner = std::ptr::null_mut(); + ret + } +} +impl Clone for BestBlock { + fn clone(&self) -> Self { + Self { + inner: if <*mut nativeBestBlock>::is_null(self.inner) { std::ptr::null_mut() } else { + Box::into_raw(Box::new(unsafe { &*self.inner }.clone())) }, + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn BestBlock_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeBestBlock)).clone() })) as *mut c_void +} +#[no_mangle] +/// Creates a copy of the BestBlock +pub extern "C" fn BestBlock_clone(orig: &BestBlock) -> BestBlock { + orig.clone() +} +/// Returns the best block from the genesis of the given network. +#[must_use] +#[no_mangle] +pub extern "C" fn BestBlock_from_genesis(mut network: crate::bitcoin::network::Network) -> BestBlock { + let mut ret = lightning::ln::channelmanager::BestBlock::from_genesis(network.into_bitcoin()); + BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true } +} + +/// Returns the best block as identified by the given block hash and height. +#[must_use] +#[no_mangle] +pub extern "C" fn BestBlock_new(mut block_hash: crate::c_types::ThirtyTwoBytes, mut height: u32) -> BestBlock { + let mut ret = lightning::ln::channelmanager::BestBlock::new(::bitcoin::hash_types::BlockHash::from_slice(&block_hash.data[..]).unwrap(), height); + BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true } +} + +/// Returns the best block hash. +#[must_use] +#[no_mangle] +pub extern "C" fn BestBlock_block_hash(this_arg: &BestBlock) -> crate::c_types::ThirtyTwoBytes { + let mut ret = unsafe { &*this_arg.inner }.block_hash(); + crate::c_types::ThirtyTwoBytes { data: ret.into_inner() } +} + +/// Returns the best block height. +#[must_use] +#[no_mangle] +pub extern "C" fn BestBlock_height(this_arg: &BestBlock) -> u32 { + let mut ret = unsafe { &*this_arg.inner }.height(); + ret +} + /// The amount of time in blocks we require our counterparty wait to claim their money (ie time /// between when we, or our watchtower, must check for them having broadcast a theft transaction). /// @@ -277,6 +361,21 @@ pub extern "C" fn ChannelDetails_get_channel_id(this_ptr: &ChannelDetails) -> *c pub extern "C" fn ChannelDetails_set_channel_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::ThirtyTwoBytes) { unsafe { &mut *this_ptr.inner }.channel_id = val.data; } +/// The position of the funding transaction in the chain. None if the funding transaction has +/// not yet been confirmed and the channel fully opened. +#[no_mangle] +pub extern "C" fn ChannelDetails_get_short_channel_id(this_ptr: &ChannelDetails) -> crate::c_types::derived::COption_u64Z { + let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.short_channel_id; + let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u64Z::None } else { { crate::c_types::derived::COption_u64Z::Some(inner_val.unwrap()) } }; + local_inner_val +} +/// The position of the funding transaction in the chain. None if the funding transaction has +/// not yet been confirmed and the channel fully opened. +#[no_mangle] +pub extern "C" fn ChannelDetails_set_short_channel_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::derived::COption_u64Z) { + let mut local_val = if val.is_some() { Some( { val.take() }) } else { None }; + unsafe { &mut *this_ptr.inner }.short_channel_id = local_val; +} /// The node_id of our counterparty #[no_mangle] pub extern "C" fn ChannelDetails_get_remote_network_id(this_ptr: &ChannelDetails) -> crate::c_types::PublicKey { @@ -580,12 +679,21 @@ pub extern "C" fn ChannelManager_new(mut fee_est: crate::chain::chaininterface:: ChannelManager { inner: Box::into_raw(Box::new(ret)), is_owned: true } } +/// Gets the current configuration applied to all new channels, as +#[must_use] +#[no_mangle] +pub extern "C" fn ChannelManager_get_current_default_configuration(this_arg: &ChannelManager) -> crate::util::config::UserConfig { + let mut ret = unsafe { &*this_arg.inner }.get_current_default_configuration(); + crate::util::config::UserConfig { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false } +} + /// Creates a new outbound channel to the given remote node and with the given value. /// -/// user_id will be provided back as user_channel_id in FundingGenerationReady and -/// FundingBroadcastSafe events to allow tracking of which events correspond with which -/// create_channel call. Note that user_channel_id defaults to 0 for inbound channels, so you -/// may wish to avoid using 0 for user_id here. +/// user_id will be provided back as user_channel_id in FundingGenerationReady events to allow +/// tracking of which events correspond with which create_channel call. Note that the +/// user_channel_id defaults to 0 for inbound channels, so you may wish to avoid using 0 for +/// user_id here. user_id has no meaning inside of LDK, it is simply copied to events and +/// otherwise ignored. /// /// If successful, will generate a SendOpenChannel message event, so you should probably poll /// PeerManager::process_events afterwards. @@ -704,16 +812,28 @@ pub extern "C" fn ChannelManager_send_payment(this_arg: &ChannelManager, route: /// Call this upon creation of a funding transaction for the given channel. /// -/// Note that ALL inputs in the transaction pointed to by funding_txo MUST spend SegWit outputs -/// or your counterparty can steal your funds! +/// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs +/// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`]. /// /// Panics if a funding transaction has already been provided for this channel. /// -/// May panic if the funding_txo is duplicative with some other channel (note that this should -/// be trivially prevented by using unique funding transaction keys per-channel). +/// May panic if the output found in the funding transaction is duplicative with some other +/// channel (note that this should be trivially prevented by using unique funding transaction +/// keys per-channel). +/// +/// Do NOT broadcast the funding transaction yourself. When we have safely received our +/// counterparty's signature the funding transaction will automatically be broadcast via the +/// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed. +/// +/// Note that this includes RBF or similar transaction replacement strategies - lightning does +/// not currently support replacing a funding transaction on an existing channel. Instead, +/// create a new channel with a conflicting funding transaction. +#[must_use] #[no_mangle] -pub extern "C" fn ChannelManager_funding_transaction_generated(this_arg: &ChannelManager, temporary_channel_id: *const [u8; 32], mut funding_txo: crate::chain::transaction::OutPoint) { - unsafe { &*this_arg.inner }.funding_transaction_generated(unsafe { &*temporary_channel_id}, *unsafe { Box::from_raw(funding_txo.take_inner()) }) +pub extern "C" fn ChannelManager_funding_transaction_generated(this_arg: &ChannelManager, temporary_channel_id: *const [u8; 32], mut funding_transaction: crate::c_types::Transaction) -> crate::c_types::derived::CResult_NoneAPIErrorZ { + let mut ret = unsafe { &*this_arg.inner }.funding_transaction_generated(unsafe { &*temporary_channel_id}, funding_transaction.into_bitcoin()); + let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::util::errors::APIError::native_into(e) }).into() }; + local_ret } /// Generates a signed node_announcement from the given arguments and creates a @@ -752,8 +872,8 @@ pub extern "C" fn ChannelManager_process_pending_htlc_forwards(this_arg: &Channe /// /// Note that in some rare cases this may generate a `chain::Watch::update_channel` call. #[no_mangle] -pub extern "C" fn ChannelManager_timer_chan_freshness_every_min(this_arg: &ChannelManager) { - unsafe { &*this_arg.inner }.timer_chan_freshness_every_min() +pub extern "C" fn ChannelManager_timer_tick_occurred(this_arg: &ChannelManager) { + unsafe { &*this_arg.inner }.timer_tick_occurred() } /// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect @@ -906,24 +1026,107 @@ pub extern "C" fn ChannelManager_as_Listen(this_arg: &ChannelManager) -> crate:: extern "C" fn ChannelManager_Listen_block_connected(this_arg: *const c_void, mut block: crate::c_types::u8slice, mut height: u32) { >::block_connected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(block.to_slice()).unwrap(), height) } -extern "C" fn ChannelManager_Listen_block_disconnected(this_arg: *const c_void, header: *const [u8; 80], mut _height: u32) { - >::block_disconnected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), _height) +extern "C" fn ChannelManager_Listen_block_disconnected(this_arg: *const c_void, header: *const [u8; 80], mut height: u32) { + >::block_disconnected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height) } -/// Updates channel state based on transactions seen in a connected block. +/// Updates channel state to take note of transactions which were confirmed in the given block +/// at the given height. +/// +/// Note that you must still call (or have called) [`update_best_block`] with the block +/// information which is included here. +/// +/// This method may be called before or after [`update_best_block`] for a given block's +/// transaction data and may be called multiple times with additional transaction data for a +/// given block. +/// +/// This method may be called for a previous block after an [`update_best_block`] call has +/// been made for a later block, however it must *not* be called with transaction data from a +/// block which is no longer in the best chain (ie where [`update_best_block`] has already +/// been informed about a blockchain reorganization which no longer includes the block which +/// corresponds to `header`). +/// +/// [`update_best_block`]: `Self::update_best_block` #[no_mangle] -pub extern "C" fn ChannelManager_block_connected(this_arg: &ChannelManager, header: *const [u8; 80], mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ, mut height: u32) { +pub extern "C" fn ChannelManager_transactions_confirmed(this_arg: &ChannelManager, header: *const [u8; 80], mut height: u32, mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ) { let mut local_txdata = Vec::new(); for mut item in txdata.into_rust().drain(..) { local_txdata.push( { let (mut orig_txdata_0_0, mut orig_txdata_0_1) = item.to_rust(); let mut local_txdata_0 = (orig_txdata_0_0, orig_txdata_0_1.into_bitcoin()); local_txdata_0 }); }; - unsafe { &*this_arg.inner }.block_connected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), &local_txdata.iter().map(|(a, b)| (*a, b)).collect::>()[..], height) + unsafe { &*this_arg.inner }.transactions_confirmed(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height, &local_txdata.iter().map(|(a, b)| (*a, b)).collect::>()[..]) } -/// Updates channel state based on a disconnected block. +/// Updates channel state with the current best blockchain tip. You should attempt to call this +/// quickly after a new block becomes available, however if multiple new blocks become +/// available at the same time, only a single `update_best_block()` call needs to be made. +/// +/// This method should also be called immediately after any block disconnections, once at the +/// reorganization fork point, and once with the new chain tip. Calling this method at the +/// blockchain reorganization fork point ensures we learn when a funding transaction which was +/// previously confirmed is reorganized out of the blockchain, ensuring we do not continue to +/// accept payments which cannot be enforced on-chain. /// -/// If necessary, the channel may be force-closed without letting the counterparty participate -/// in the shutdown. +/// In both the block-connection and block-disconnection case, this method may be called either +/// once per block connected or disconnected, or simply at the fork point and new tip(s), +/// skipping any intermediary blocks. #[no_mangle] -pub extern "C" fn ChannelManager_block_disconnected(this_arg: &ChannelManager, header: *const [u8; 80]) { - unsafe { &*this_arg.inner }.block_disconnected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap()) +pub extern "C" fn ChannelManager_update_best_block(this_arg: &ChannelManager, header: *const [u8; 80], mut height: u32) { + unsafe { &*this_arg.inner }.update_best_block(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height) +} + +/// Gets the set of txids which should be monitored for their confirmation state. +/// +/// If you're providing information about reorganizations via [`transaction_unconfirmed`], this +/// is the set of transactions which you may need to call [`transaction_unconfirmed`] for. +/// +/// This may be useful to poll to determine the set of transactions which must be registered +/// with an Electrum server or for which an Electrum server needs to be polled to determine +/// transaction confirmation state. +/// +/// This may update after any [`transactions_confirmed`] or [`block_connected`] call. +/// +/// Note that this is NOT the set of transactions which must be included in calls to +/// [`transactions_confirmed`] if they are confirmed, but a small subset of it. +/// +/// [`transactions_confirmed`]: Self::transactions_confirmed +/// [`transaction_unconfirmed`]: Self::transaction_unconfirmed +/// [`block_connected`]: chain::Listen::block_connected +#[must_use] +#[no_mangle] +pub extern "C" fn ChannelManager_get_relevant_txids(this_arg: &ChannelManager) -> crate::c_types::derived::CVec_TxidZ { + let mut ret = unsafe { &*this_arg.inner }.get_relevant_txids(); + let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::c_types::ThirtyTwoBytes { data: item.into_inner() } }); }; + local_ret.into() +} + +/// Marks a transaction as having been reorganized out of the blockchain. +/// +/// If a transaction is included in [`get_relevant_txids`], and is no longer in the main branch +/// of the blockchain, this function should be called to indicate that the transaction should +/// be considered reorganized out. +/// +/// Once this is called, the given transaction will no longer appear on [`get_relevant_txids`], +/// though this may be called repeatedly for a given transaction without issue. +/// +/// Note that if the transaction is confirmed on the main chain in a different block (indicated +/// via a call to [`transactions_confirmed`]), it may re-appear in [`get_relevant_txids`], thus +/// be very wary of race-conditions wherein the final state of a transaction indicated via +/// these APIs is not the same as its state on the blockchain. +/// +/// [`transactions_confirmed`]: Self::transactions_confirmed +/// [`get_relevant_txids`]: Self::get_relevant_txids +#[no_mangle] +pub extern "C" fn ChannelManager_transaction_unconfirmed(this_arg: &ChannelManager, txid: *const [u8; 32]) { + unsafe { &*this_arg.inner }.transaction_unconfirmed(&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*txid }[..]).unwrap()) +} + +/// Blocks until ChannelManager needs to be persisted or a timeout is reached. It returns a bool +/// indicating whether persistence is necessary. Only one listener on +/// `await_persistable_update` or `await_persistable_update_timeout` is guaranteed to be woken +/// up. +/// Note that the feature `allow_wallclock_use` must be enabled to use this function. +#[must_use] +#[no_mangle] +pub extern "C" fn ChannelManager_await_persistable_update_timeout(this_arg: &ChannelManager, mut max_wait: u64) -> bool { + let mut ret = unsafe { &*this_arg.inner }.await_persistable_update_timeout(std::time::Duration::from_secs(max_wait)); + ret } /// Blocks until ChannelManager needs to be persisted. Only one listener on @@ -974,7 +1177,7 @@ pub extern "C" fn ChannelManager_as_ChannelMessageHandler(this_arg: &ChannelMana MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider { this_arg: unsafe { (*this_arg).inner as *mut c_void }, free: None, - get_and_clear_pending_msg_events: ChannelManager_ChannelMessageHandler_get_and_clear_pending_msg_events, + get_and_clear_pending_msg_events: ChannelManager_MessageSendEventsProvider_get_and_clear_pending_msg_events, }, } } @@ -1039,12 +1242,6 @@ extern "C" fn ChannelManager_ChannelMessageHandler_peer_connected(this_arg: *con extern "C" fn ChannelManager_ChannelMessageHandler_handle_error(this_arg: *const c_void, mut counterparty_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ErrorMessage) { >::handle_error(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &counterparty_node_id.into_rust(), unsafe { &*msg.inner }) } -#[must_use] -extern "C" fn ChannelManager_ChannelMessageHandler_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ { - let mut ret = >::get_and_clear_pending_msg_events(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, ); - let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); }; - local_ret.into() -} #[no_mangle] /// Serialize the ChannelManager object into a byte array which can be read by ChannelManager_read