Skip to content

Commit 7b2577d

Browse files
committed
support BlockNotifier for ffi
1 parent 5071a96 commit 7b2577d

File tree

7 files changed

+126
-10
lines changed

7 files changed

+126
-10
lines changed

bindings/src/adaptors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bitcoin::secp256k1;
1313
use lightning::{
1414
chain::chaininterface::{BroadcasterInterface, FeeEstimator, ConfirmationTarget, ChainWatchInterface, ChainError},
1515
util::logger::{Logger, Record, Level},
16-
util::ser::{Writeable, Writer},
16+
util::ser::{Writer},
1717
ln::peer_handler::SocketDescriptor,
1818
ln::msgs::ErrorAction,
1919
chain::chaininterface::ChainWatchInterfaceUtil,

bindings/src/adaptors/primitives.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{
22
convert::{TryFrom},
3-
fmt::{Formatter}
3+
fmt::{Formatter},
4+
io::{Error}
45
};
56

67
use bitcoin::{
@@ -16,16 +17,14 @@ use lightning::{
1617
routing::router::{Route},
1718
util::ser::{Readable, Writeable},
1819
util::events::Event,
19-
chain::transaction::OutPoint
20+
chain::transaction::OutPoint,
21+
ln::channelmanager::PaymentPreimage,
22+
util::ser::Writer
2023
};
2124
use crate::{
2225
FFIResult,
2326
is_null::IsNull
2427
};
25-
use lightning::ln::channelmanager::PaymentPreimage;
26-
use std::io::{Error, Read};
27-
use lightning::ln::msgs::DecodeError;
28-
use lightning::util::ser::Writer;
2928

3029
#[derive(Debug, Clone)]
3130
#[repr(C)]

bindings/src/blocknotifier.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use std::sync::Arc;
2+
use lightning::chain::chaininterface::{BlockNotifier, ChainListener};
3+
use crate::{
4+
HandleShared,
5+
FFIResult,
6+
Ref,
7+
Out,
8+
channelmanager::{FFIArcChannelManagerHandle, FFIArcChannelManager},
9+
adaptors::{chain_watch_interface_fn, FFIChainWatchInterface}
10+
};
11+
use crate::adaptors::{FFINetwork, ffilogger_fn, FFILogger};
12+
use bitcoin::BlockHeader;
13+
14+
type FFIBlockNotifier = BlockNotifier<'static, Arc<dyn ChainListener>, Arc<FFIChainWatchInterface>>;
15+
type FFIBlockNotifierHandle<'a> = HandleShared<'a, FFIBlockNotifier>;
16+
17+
ffi! {
18+
19+
fn create_block_notifier(
20+
network_ref: FFINetwork,
21+
log_ptr: Ref<ffilogger_fn::LogExtern>,
22+
install_watch_tx_ptr: Ref<chain_watch_interface_fn::InstallWatchTxPtr>,
23+
install_watch_outpoint_ptr: Ref<chain_watch_interface_fn::InstallWatchOutpointPtr>,
24+
watch_all_txn_ptr: Ref<chain_watch_interface_fn::WatchAllTxnPtr>,
25+
get_chain_utxo_ptr: Ref<chain_watch_interface_fn::GetChainUtxoPtr>,
26+
handle: Out<FFIBlockNotifierHandle>
27+
) -> FFIResult {
28+
let network = network_ref.to_network();
29+
let log_ref = unsafe_block!("" => log_ptr.as_ref());
30+
let logger_arc = Arc::new( FFILogger{ log_ptr: *log_ref } );
31+
32+
let install_watch_tx_ref = unsafe_block!("function pointer lives as long as ChainWatchInterface and it points to valid data" => install_watch_tx_ptr.as_ref());
33+
let install_watch_outpoint_ref = unsafe_block!("function pointer lives as long as ChainWatchInterface and it points to valid data" => install_watch_outpoint_ptr.as_ref());
34+
let watch_all_txn_ref = unsafe_block!("function pointer lives as long as ChainWatchInterface and it points to valid data" => watch_all_txn_ptr.as_ref());
35+
let get_chain_utxo_ref = unsafe_block!("function pointer lives as long as ChainWatchInterface and it points to valid data" => get_chain_utxo_ptr.as_ref());
36+
let chain_watch_interface_arc =
37+
Arc::new(FFIChainWatchInterface::new(
38+
*install_watch_tx_ref,
39+
*install_watch_outpoint_ref,
40+
*watch_all_txn_ref,
41+
*get_chain_utxo_ref,
42+
network,
43+
logger_arc.clone()
44+
));
45+
let block_notifier = FFIBlockNotifier::new(chain_watch_interface_arc);
46+
unsafe_block!("We know handle is not null by wrapper macro. And we know `Out` is writable" => handle.init(HandleShared::alloc(block_notifier)));
47+
FFIResult::ok()
48+
}
49+
50+
fn register_channel_manager(
51+
channel_manager: FFIArcChannelManagerHandle,
52+
handle: FFIBlockNotifierHandle
53+
) -> FFIResult {
54+
let chan_man: Arc<FFIArcChannelManager> = unsafe_block!("We know the handle points to valid channel_manager" => channel_manager.as_arc());
55+
let block_notifier: &FFIBlockNotifier = unsafe_block!("We know the handle pointers to valid block notifier" => handle.as_ref());
56+
block_notifier.register_listener(chan_man);
57+
FFIResult::ok()
58+
}
59+
60+
fn unregister_channel_manager(
61+
channel_manager: FFIArcChannelManagerHandle,
62+
handle: FFIBlockNotifierHandle
63+
) -> FFIResult {
64+
let chan_man: Arc<FFIArcChannelManager> = unsafe_block!("We know the handle points to valid channel_manager" => channel_manager.as_arc());
65+
let block_notifier: &FFIBlockNotifier = unsafe_block!("We know the handle pointers to valid block notifier" => handle.as_ref());
66+
block_notifier.unregister_listener(chan_man);
67+
FFIResult::ok()
68+
}
69+
70+
fn block_connected(
71+
block_ptr: Ref<u8>,
72+
block_len: usize,
73+
height: u32,
74+
handle: FFIBlockNotifierHandle) -> FFIResult {
75+
let block_notifier: &FFIBlockNotifier = unsafe_block!("We know the handle pointers to valid block notifier" => handle.as_ref());
76+
let block_bytes = unsafe_block!("block_ptr points to valid buffer of block_len length" => block_ptr.as_bytes(block_len));
77+
let block = bitcoin::consensus::deserialize(block_bytes)?;
78+
block_notifier.block_connected(&block, height);
79+
FFIResult::ok()
80+
}
81+
82+
fn block_disconnected(
83+
block_header_ptr: Ref<u8>,
84+
block_header_len: usize,
85+
height: u32,
86+
handle: FFIBlockNotifierHandle
87+
) -> FFIResult {
88+
let block_notifier: &FFIBlockNotifier = unsafe_block!("We know the handle pointers to valid block notifier" => handle.as_ref());
89+
90+
let block_header_bytes: &[u8] = unsafe_block!("We know it points to valid buffer of specified length" => block_header_ptr.as_bytes(block_header_len));
91+
let block_header: BlockHeader = bitcoin::consensus::encode::deserialize(block_header_bytes)?;
92+
block_notifier.block_disconnected(&block_header, height);
93+
FFIResult::ok()
94+
}
95+
96+
fn release_block_notifier(handle: FFIBlockNotifierHandle) -> FFIResult {
97+
unsafe_block!("The upstream caller guarantees the handle will not be accessed after being freed" => FFIBlockNotifierHandle::dealloc(handle, |mut handle| {
98+
// We keep reference to listeners from wrapper side (as a `SafeHandle`
99+
// to a `ChannelManager`) so that we can call methods
100+
// on it. So disposing it is their job. Not ours.
101+
std::mem::forget(handle.listeners);
102+
FFIResult::ok()
103+
}))
104+
}
105+
}

bindings/src/channelmanager.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{
44
time::{SystemTime, UNIX_EPOCH}
55
};
66

7-
use bitcoin::secp256k1;
7+
use bitcoin::{secp256k1, BlockHeader, Transaction};
88
use lightning::{
99
util::{
1010
config::UserConfig,
@@ -19,6 +19,8 @@ use lightning::{
1919
transaction::OutPoint
2020
},
2121
routing::router::Route,
22+
ln::channelmanager::{PaymentSecret, PaymentPreimage},
23+
chain::chaininterface::ChainListener
2224
};
2325

2426
use crate::{
@@ -36,7 +38,14 @@ use crate::{
3638
},
3739
utils::into_fixed_buffer,
3840
};
39-
use lightning::ln::channelmanager::{PaymentSecret, PaymentPreimage};
41+
42+
#[inline]
43+
pub fn slice_to_be32(v: &[u8]) -> u32 {
44+
((v[0] as u32) << 8*3) |
45+
((v[1] as u32) << 8*2) |
46+
((v[2] as u32) << 8*1) |
47+
((v[3] as u32) << 8*0)
48+
}
4049

4150
pub type FFIManyChannelMonitor = SimpleManyChannelMonitor<OutPoint, InMemoryChannelKeys, Arc<FFIBroadCaster>, Arc<FFIFeeEstimator>, Arc<FFILogger>, Arc<FFIChainWatchInterface>>;
4251
pub type FFIArcChannelManager = ChannelManager<InMemoryChannelKeys, Arc<FFIManyChannelMonitor>, Arc<FFIBroadCaster>, Arc<KeysManager>, Arc<FFIFeeEstimator>, Arc<FFILogger>>;

bindings/src/is_null.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ impl<T: ?Sized> IsNull for *mut T {
4444
}
4545

4646
never_null!(usize, isize, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
47+
never_null!(crate::adaptors::FFINetwork);

bindings/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ mod adaptors;
2626

2727
mod channelmanager;
2828
mod peermanager;
29+
mod blocknotifier;
2930
mod error;
3031
mod handle;
3132

lightning/src/chain/chaininterface.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ pub type BlockNotifierRef<'a, C> = BlockNotifier<'a, &'a ChainListener, C>;
238238
/// you should default to using a BlockNotifierRef, and use a BlockNotifierArc instead when you
239239
/// require ChainListeners with static lifetimes, such as when you're using lightning-net-tokio.
240240
pub struct BlockNotifier<'a, CL: Deref<Target = ChainListener + 'a> + 'a, C: Deref> where C::Target: ChainWatchInterface {
241-
listeners: Mutex<Vec<CL>>,
241+
/// Listeners to which we notify about information for a new block.
242+
pub listeners: Mutex<Vec<CL>>,
242243
chain_monitor: C,
243244
phantom: PhantomData<&'a ()>,
244245
}

0 commit comments

Comments
 (0)