Skip to content

Commit 00e6b09

Browse files
committed
update: FFI PeerManager create/dispose methods
1 parent 12989ab commit 00e6b09

File tree

6 files changed

+493
-72
lines changed

6 files changed

+493
-72
lines changed

bindings/src/adaptors/mod.rs

Lines changed: 249 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,44 @@
1-
use std::ffi::{CString};
2-
use std::sync::Arc;
1+
use std::{
2+
io::Error,
3+
ffi::{CString},
4+
hash::{Hasher, Hash},
5+
sync::Arc
6+
};
37

48
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
5-
use bitcoin::blockdata::transaction::Transaction;
6-
use bitcoin::blockdata::script::Script;
7-
use bitcoin::blockdata::block::Block;
8-
use bitcoin::consensus::serialize as bitcoin_serialize;
9+
use bitcoin::{
10+
blockdata::transaction::Transaction,
11+
blockdata::script::Script,
12+
blockdata::block::Block,
13+
consensus::serialize as bitcoin_serialize
14+
};
915

10-
use lightning::util::logger::{Logger, Record, Level};
11-
12-
use lightning::chain::chaininterface::{BroadcasterInterface,FeeEstimator,ConfirmationTarget, ChainWatchInterface, ChainError};
13-
use lightning::chain::keysinterface::{InMemoryChannelKeys};
14-
use lightning::chain::transaction::{OutPoint};
15-
16-
use lightning::ln::channelmonitor::{ManyChannelMonitor, ChannelMonitor, HTLCUpdate, ChannelMonitorUpdateErr, ChannelMonitorUpdate};
16+
use lightning::{
17+
chain::transaction::{OutPoint},
18+
chain::keysinterface::{InMemoryChannelKeys},
19+
chain::chaininterface::{BroadcasterInterface, FeeEstimator, ConfirmationTarget, ChainWatchInterface, ChainError},
20+
util::logger::{Logger, Record, Level},
21+
ln::channelmonitor::{ManyChannelMonitor, ChannelMonitor, HTLCUpdate, ChannelMonitorUpdateErr, ChannelMonitorUpdate},
22+
util::ser::{Writeable, Writer},
23+
ln::peer_handler::SocketDescriptor,
24+
ln::msgs::ErrorAction
25+
};
1726

1827
pub mod primitives;
1928
use primitives::*;
20-
use lightning::util::ser::{Writeable, Writer};
21-
use std::io::Error;
29+
use std::convert::TryFrom;
30+
use lightning::ln::msgs::{ErrorMessage, RoutingMessageHandler, HTLCFailChannelUpdate, ChannelAnnouncement, NodeAnnouncement, LightningError, ChannelUpdate};
31+
use std::ffi::CStr;
32+
use std::ptr::NonNull;
33+
34+
type cstr = NonNull<i8>;
35+
36+
#[derive(PartialOrd, PartialEq, Eq, Ord, Debug, Copy, Clone)]
37+
#[repr(u8)]
38+
pub enum Bool { False = 0, True = 1 }
39+
impl Bool {
40+
pub fn to_bool(&self) -> bool { *self == Bool::True }
41+
}
2242

2343
pub mod broadcaster_fn {
2444
use crate::adaptors::primitives::FFITransaction;
@@ -135,11 +155,11 @@ pub struct FFILogRecord {
135155
/// The verbosity level of the message.
136156
pub level: FFILogLevel,
137157
/// The message body.
138-
pub args: *const i8,
158+
pub args: cstr,
139159
/// The module path of the message.
140-
pub module_path: *const i8,
160+
pub module_path: cstr,
141161
/// The source file containing the message.
142-
pub file: *const i8,
162+
pub file: cstr,
143163
/// The line containing the message.
144164
pub line: u32,
145165
}
@@ -162,9 +182,9 @@ impl Logger for FFILogger {
162182
let ffi_record =
163183
FFILogRecord {
164184
level: rec.level.into(),
165-
args: args.as_ptr(),
166-
module_path: module_path.as_ptr(),
167-
file: file.as_ptr(),
185+
args: NonNull::new(args.as_ptr() as *mut _).unwrap(),
186+
module_path: NonNull::new(module_path.as_ptr() as *mut _).unwrap(),
187+
file: NonNull::new(file.as_ptr() as *mut _).unwrap(),
168188
line: rec.line,
169189
};
170190
(self.log_ptr)(&ffi_record as *const _);
@@ -226,3 +246,211 @@ impl ChainWatchInterface for FFIChainWatchInterface {
226246
}
227247
}
228248

249+
pub mod socket_descriptor_fn {
250+
use super::FFIBytes;
251+
pub type SendData = extern "cdecl" fn (data: *const FFIBytes, resume_read: u8) -> usize;
252+
pub type DisconnectSocket = extern "cdecl" fn ();
253+
}
254+
255+
#[repr(C)]
256+
#[derive(Clone)]
257+
pub struct FFISocketDescriptor {
258+
pub index: usize,
259+
pub send_data_ptr: socket_descriptor_fn::SendData,
260+
pub disconnect_socket_ptr: socket_descriptor_fn::DisconnectSocket,
261+
}
262+
263+
impl PartialEq for FFISocketDescriptor {
264+
fn eq(&self, other: &Self) -> bool {
265+
self.index == other.index
266+
}
267+
}
268+
impl Eq for FFISocketDescriptor {}
269+
impl Hash for FFISocketDescriptor {
270+
fn hash<H: Hasher>(&self, state: &mut H) {
271+
self.index.hash(state)
272+
}
273+
}
274+
275+
impl SocketDescriptor for FFISocketDescriptor {
276+
fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize {
277+
let r: FFIBytes = data.into();
278+
(self.send_data_ptr)(&r as *const _, resume_read as u8)
279+
}
280+
281+
fn disconnect_socket(&mut self) {
282+
(self.disconnect_socket_ptr)()
283+
}
284+
}
285+
286+
#[repr(u8)]
287+
#[derive(Debug,Clone)]
288+
pub enum FFIErrorActionType {
289+
DisconnectPeer = 0u8,
290+
/// The peer did something harmless that we weren't able to process, just log and ignore
291+
IgnoreError,
292+
/// The peer did something incorrect. Tell them.
293+
SendErrorMessage,
294+
}
295+
296+
#[repr(C)]
297+
#[derive(Debug, Clone)]
298+
pub struct FFIErrorMsg {
299+
pub channel_id: [u8; 32],
300+
pub data: cstr,
301+
}
302+
303+
impl From<FFIErrorMsg> for ErrorMessage {
304+
fn from(msg: FFIErrorMsg) -> Self {
305+
let data = unsafe_block!("We know pointer is non-null" => CStr::from_ptr(msg.data.as_ptr()) );
306+
ErrorMessage {
307+
data: data.to_str().unwrap().to_owned(),
308+
channel_id: msg.channel_id
309+
}
310+
}
311+
}
312+
313+
#[repr(C)]
314+
#[derive(Debug, Clone)]
315+
pub struct FFIErrorAction {
316+
ty: FFIErrorActionType,
317+
payload: Option<*const FFIErrorMsg>
318+
}
319+
320+
impl From<FFIErrorAction> for ErrorAction {
321+
fn from(x: FFIErrorAction) -> Self {
322+
match x.ty {
323+
FFIErrorActionType::DisconnectPeer => {
324+
ErrorAction::DisconnectPeer {
325+
msg: x.payload.map(|msg| {
326+
From::from(unsafe_block!("`from` conversion consumes x" => (*msg).clone()))
327+
})
328+
}
329+
},
330+
FFIErrorActionType::IgnoreError => {
331+
ErrorAction::IgnoreError
332+
},
333+
FFIErrorActionType::SendErrorMessage => {
334+
match x.payload {
335+
None => panic!(format!("Inconsistent enum {:?}", x)),
336+
Some(msg) => {
337+
let msg = unsafe_block!("`from` conversion consumes x" => (*msg).clone()).into();
338+
ErrorAction::SendErrorMessage { msg }
339+
}
340+
}
341+
}
342+
}
343+
}
344+
}
345+
346+
#[derive(Clone)]
347+
#[repr(C)]
348+
pub struct FFILightningError {
349+
/// A human-readable message describing the error
350+
pub err: cstr,
351+
/// The action which should be taken against the offending peer.
352+
pub action: FFIErrorAction,
353+
}
354+
355+
impl From<FFILightningError> for LightningError {
356+
fn from(v: FFILightningError) -> Self {
357+
let err = unsafe_block!("We know error msg is non-null c string" => CStr::from_ptr(v.err.as_ptr()) );
358+
LightningError {
359+
err: err.to_str().unwrap(),
360+
action: v.action.into()
361+
}
362+
}
363+
}
364+
365+
pub mod routing_msg_descriptor_fn {
366+
use super::*;
367+
use crate::adaptors::primitives::PublicKey;
368+
use lightning::ln::msgs::{NodeAnnouncement, LightningError, ChannelAnnouncement, ChannelUpdate, HTLCFailChannelUpdate};
369+
370+
/// Handle an incoming node_announcement message, returning true if it should be forwarded on,
371+
/// false or returning an Err otherwise.
372+
pub type HandleNodeAnnouncement = extern "cdecl" fn (msg: *const FFIBytes, error: *mut FFILightningError) -> Bool;
373+
/// Handle a channel_announcement message, returning true if it should be forwarded on, false
374+
/// or returning an Err otherwise.
375+
pub type HandleChannelAnnouncement = extern "cdecl" fn (msg: *const FFIBytes, error: *mut FFILightningError) -> Bool;
376+
/// Handle an incoming channel_update message, returning true if it should be forwarded on,
377+
/// false or returning an Err otherwise.
378+
pub type HandleChannelUpdate = extern "cdecl" fn (msg: *const FFIBytes, error: *mut FFILightningError) -> Bool;
379+
/// Handle some updates to the route graph that we learned due to an outbound failed payment.
380+
pub type HandleHTLCFailChannelUpdate = extern "cdecl" fn (update: *const FFIBytes);
381+
/// Gets a subset of the channel announcements and updates required to dump our routing table
382+
/// to a remote node, starting at the short_channel_id indicated by starting_point and
383+
/// including the batch_amount entries immediately higher in numerical value than starting_point.
384+
/// Return type is serialized `Vec<(ChannelAnnouncement, ChannelUpdate, ChannelUpdate)>`
385+
pub type GetNextChannelAnnouncements = extern "cdecl" fn (starting_point: u64, batch_amount: u8) -> FFIBytes<'static>;
386+
/// Gets a subset of the node announcements required to dump our routing table to a remote node,
387+
/// starting at the node *after* the provided publickey and including batch_amount entries
388+
/// immediately higher (as defined by <PublicKey as Ord>::cmp) than starting_point.
389+
/// If None is provided for starting_point, we start at the first node.
390+
/// Return type is binary serialized `Vec<NodeAnnouncement>` .
391+
pub type GetNextNodeAnnouncements = extern "cdecl" fn (starting_point: Option<*const PublicKey>, batch_amount: u8) -> FFIBytes<'static>;
392+
/// Returns whether a full sync should be requested from a peer.
393+
pub type ShouldRequestFullSync = extern "cdecl" fn (node_id: NonNull<PublicKey>) -> Bool;
394+
}
395+
396+
pub struct FFIRoutingMsgHandler {
397+
pub handle_node_announcement_ptr: routing_msg_descriptor_fn::HandleNodeAnnouncement,
398+
pub handle_channel_announcement_ptr: routing_msg_descriptor_fn::HandleChannelAnnouncement,
399+
pub handle_channel_update_ptr: routing_msg_descriptor_fn::HandleChannelUpdate,
400+
pub handle_htlc_fail_channel_update_ptr: routing_msg_descriptor_fn::HandleHTLCFailChannelUpdate,
401+
pub get_next_channel_announcements_ptr: routing_msg_descriptor_fn::GetNextChannelAnnouncements,
402+
pub get_next_node_announcements_ptr: routing_msg_descriptor_fn::GetNextNodeAnnouncements,
403+
pub should_request_full_sync_ptr: routing_msg_descriptor_fn::ShouldRequestFullSync
404+
}
405+
406+
pub struct VecWriter(pub Vec<u8>);
407+
impl Writer for VecWriter {
408+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error> {
409+
self.0.extend_from_slice(buf);
410+
Ok(())
411+
}
412+
413+
fn size_hint(&mut self, size: usize) {
414+
self.0.reserve_exact(size)
415+
}
416+
}
417+
418+
impl RoutingMessageHandler for FFIRoutingMsgHandler {
419+
fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<bool, LightningError> {
420+
let mut w = VecWriter(Vec::new());
421+
msg.write(&mut w);
422+
let bytes = FFIBytes::from(w.0.into_boxed_slice());
423+
let e = std::ptr::null_mut();
424+
let is_success = (self.handle_node_announcement_ptr)(&bytes as *const _, e);
425+
if e.is_null() {
426+
Ok(is_success.to_bool())
427+
} else {
428+
let e = unsafe_block!("we know the error is not a null pointer" => (*e).clone());
429+
Err(e.into())
430+
}
431+
}
432+
433+
fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result<bool, LightningError> {
434+
unimplemented!()
435+
}
436+
437+
fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<bool, LightningError> {
438+
unimplemented!()
439+
}
440+
441+
fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate) {
442+
unimplemented!()
443+
}
444+
445+
fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, ChannelUpdate, ChannelUpdate)> {
446+
unimplemented!()
447+
}
448+
449+
fn get_next_node_announcements(&self, starting_point: Option<&secp256k1::PublicKey>, batch_amount: u8) -> Vec<NodeAnnouncement> {
450+
unimplemented!()
451+
}
452+
453+
fn should_request_full_sync(&self, node_id: &secp256k1::PublicKey) -> bool {
454+
unimplemented!()
455+
}
456+
}

bindings/src/adaptors/primitives.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,17 @@ macro_rules! array_struct{
6565
#[doc="The length must be [the same as a byte number of secp256k1 secret key](secp256k1::constants::SECRET_KEY_SIZE)"]
6666
array_struct!(SecretKey, u8);
6767

68+
impl<'a> TryFrom<SecretKey<'a>> for secp256k1::SecretKey {
69+
type Error = FFIResult;
70+
71+
fn try_from(value: SecretKey<'a>) -> Result<Self, Self::Error> {
72+
let s = value.as_ref();
73+
secp256k1::SecretKey::from_slice(s).map_err(|_| FFIResult::invalid_data_length())
74+
}
75+
}
76+
6877
#[doc="The length must be [the same as a byte number of secp256k1 public key] `secp256k1::constants::PUBLIC_KEY_SIZE`"]
6978
array_struct!(PublicKey, u8);
70-
7179
impl<'a> TryFrom<PublicKey<'a>> for secp256k1::PublicKey {
7280
type Error = FFIResult;
7381

@@ -166,6 +174,8 @@ array_struct!(FFITransaction, u8);
166174
array_struct!(FFIBlock, u8);
167175
array_struct!(FFIEvents, u8);
168176

177+
/// General purpose byte array which has to cross ffi-boundary
178+
array_struct!(FFIBytes, u8);
169179

170180
impl<'a> TryFrom<Vec<Event>> for FFIEvents<'a> {
171181
type Error = lightning::ln::msgs::DecodeError;

0 commit comments

Comments
 (0)