X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-c-bindings%2Fsrc%2Fchain%2Fmod.rs;h=fb72263f39c45ee5dcc6110d4f50384d3bb75712;hb=7caadd446bd497cfd47e753fa8a931cb49d5b6d6;hp=6ea4d99db9df9e403b29f8aa8f4a52ede7df17d4;hpb=fc7df54f8dc3baf710371e2ad2beb862946d5b1c;p=rust-lightning diff --git a/lightning-c-bindings/src/chain/mod.rs b/lightning-c-bindings/src/chain/mod.rs index 6ea4d99d..fb72263f 100644 --- a/lightning-c-bindings/src/chain/mod.rs +++ b/lightning-c-bindings/src/chain/mod.rs @@ -77,7 +77,7 @@ use lightning::chain::Access as rustAccess; impl rustAccess for Access { fn get_utxo(&self, genesis_hash: &bitcoin::hash_types::BlockHash, short_channel_id: u64) -> Result { let mut ret = (self.get_utxo)(self.this_arg, genesis_hash.as_inner(), short_channel_id); - let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })}; + let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) }).into_native() })}; local_ret } } @@ -100,6 +100,50 @@ impl Drop for Access { } } } +/// The `Listen` trait is used to be notified of when blocks have been connected or disconnected +/// from the chain. +/// +/// Useful when needing to replay chain data upon startup or as new chain events occur. +#[repr(C)] +pub struct Listen { + pub this_arg: *mut c_void, + /// Notifies the listener that a block was added at the given height. + pub block_connected: extern "C" fn (this_arg: *const c_void, block: crate::c_types::u8slice, height: u32), + /// Notifies the listener that a block was removed at the given height. + pub block_disconnected: extern "C" fn (this_arg: *const c_void, header: *const [u8; 80], height: u32), + pub free: Option, +} + +use lightning::chain::Listen as rustListen; +impl rustListen for Listen { + fn block_connected(&self, block: &bitcoin::blockdata::block::Block, height: u32) { + let mut local_block = ::bitcoin::consensus::encode::serialize(block); + (self.block_connected)(self.this_arg, crate::c_types::u8slice::from_slice(&local_block), height) + } + fn block_disconnected(&self, header: &bitcoin::blockdata::block::BlockHeader, height: u32) { + let mut local_header = { let mut s = [0u8; 80]; s[..].copy_from_slice(&::bitcoin::consensus::encode::serialize(header)); s }; + (self.block_disconnected)(self.this_arg, &local_header, height) + } +} + +// We're essentially a pointer already, or at least a set of pointers, so allow us to be used +// directly as a Deref trait in higher-level structs: +impl std::ops::Deref for Listen { + type Target = Self; + fn deref(&self) -> &Self { + self + } +} +/// Calls the free function if one is set +#[no_mangle] +pub extern "C" fn Listen_free(this_ptr: Listen) { } +impl Drop for Listen { + fn drop(&mut self) { + if let Some(f) = self.free { + f(self.this_arg); + } + } +} /// The `Watch` trait defines behavior for watching on-chain activity pertaining to channels as /// blocks are connected and disconnected. /// @@ -154,21 +198,20 @@ unsafe impl Send for Watch {} unsafe impl Sync for Watch {} use lightning::chain::Watch as rustWatch; -impl rustWatch for Watch { - type Keys = crate::chain::keysinterface::ChannelKeys; - fn watch_channel(&self, funding_txo: lightning::chain::transaction::OutPoint, monitor: lightning::chain::channelmonitor::ChannelMonitor) -> Result<(), lightning::chain::channelmonitor::ChannelMonitorUpdateErr> { +impl rustWatch for Watch { + fn watch_channel(&self, funding_txo: lightning::chain::transaction::OutPoint, monitor: lightning::chain::channelmonitor::ChannelMonitor) -> Result<(), lightning::chain::channelmonitor::ChannelMonitorUpdateErr> { let mut ret = (self.watch_channel)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo)), is_owned: true }, crate::chain::channelmonitor::ChannelMonitor { inner: Box::into_raw(Box::new(monitor)), is_owned: true }); - let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })}; + 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 } fn update_channel(&self, funding_txo: lightning::chain::transaction::OutPoint, update: lightning::chain::channelmonitor::ChannelMonitorUpdate) -> Result<(), lightning::chain::channelmonitor::ChannelMonitorUpdateErr> { let mut ret = (self.update_channel)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo)), is_owned: true }, crate::chain::channelmonitor::ChannelMonitorUpdate { inner: Box::into_raw(Box::new(update)), is_owned: true }); - let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })}; + 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 } fn release_pending_monitor_events(&self) -> Vec { let mut ret = (self.release_pending_monitor_events)(self.this_arg); - let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { *unsafe { Box::from_raw(item.take_ptr()) } }); }; + let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { item.into_native() }); }; local_ret } }