Skip to content

Commit 68ebe5f

Browse files
committed
update
1 parent 6828535 commit 68ebe5f

File tree

11 files changed

+338
-48
lines changed

11 files changed

+338
-48
lines changed

bindings/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ secp256k1 = "0.15"
1818
bitcoin = "0.21"
1919
bitcoin_hashes = "0.7"
2020
hex = { version = "0.3", optional = true }
21+
libc = "0.2.68"
2122

2223
[build-dependencies]
2324
cbindgen = "0.13.1"

bindings/hoge.rs

Whitespace-only changes.

bindings/src/adaptors/mod.rs

Lines changed: 148 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
use std::sync::{Arc};
2+
use std::ffi::{CStr, CString, NulError};
3+
use std::convert::TryFrom;
24

3-
use secp256k1::constants::{SECRET_KEY_SIZE, PUBLIC_KEY_SIZE};
5+
use libc::c_char;
6+
7+
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
48
use bitcoin::util::key::PrivateKey;
59
use bitcoin::blockdata::transaction::Transaction;
10+
use bitcoin::blockdata::script::Script;
11+
use bitcoin::blockdata::block::Block;
612
use bitcoin::consensus::encode::serialize;
713

8-
use lightning::util::logger::{Logger, Record};
14+
use lightning::util::logger::{Logger, Record, Level};
915

10-
use lightning::chain::chaininterface::{BroadcasterInterface,FeeEstimator,ConfirmationTarget};
16+
use lightning::chain::chaininterface::{BroadcasterInterface,FeeEstimator,ConfirmationTarget, ChainWatchInterface, ChainError};
1117
use lightning::chain::keysinterface::{KeysManager, InMemoryChannelKeys};
1218
use lightning::chain::transaction::{OutPoint};
1319

@@ -17,17 +23,8 @@ use lightning::ln::channelmonitor::{ManyChannelMonitor, ChannelMonitor, HTLCUpda
1723
use crate::error::FFIResult;
1824
use crate::handle::{Out, Ref, RefMut,HandleShared};
1925

20-
#[repr(transparent)]
21-
struct SecretKey([u8; SECRET_KEY_SIZE]);
22-
23-
#[repr(transparent)]
24-
struct PublicKey([u8; PUBLIC_KEY_SIZE]);
25-
26-
#[repr(C)]
27-
struct FFIOutPoint {
28-
txid: [u8; 32],
29-
index: u16
30-
}
26+
pub mod primitives;
27+
use primitives::*;
3128

3229
#[repr(C)]
3330
pub struct FFIManyChannelMonitor {
@@ -64,26 +61,50 @@ impl ManyChannelMonitor<InMemoryChannelKeys> for FFIManyChannelMonitor {
6461
}
6562
}
6663

64+
pub mod BroadcasterFn {
65+
use crate::adaptors::primitives::FFITransaction;
66+
pub type broadcast_transaction_ptr = extern "cdecl" fn(tx: *const FFITransaction);
67+
}
68+
6769
#[repr(C)]
6870
pub struct FFIBroadCaster {
69-
broadcast_transaction_ptr: extern "cdecl" fn(tx: *const u8, tx_len: u64),
71+
pub broadcast_transaction_ptr: BroadcasterFn::broadcast_transaction_ptr,
7072
}
7173

7274
impl BroadcasterInterface for FFIBroadCaster {
7375
fn broadcast_transaction(&self, tx: &Transaction) {
74-
let b_tx = serialize(tx);
75-
(self.broadcast_transaction_ptr)(b_tx.as_ptr(), b_tx.len() as u64)
76+
(self.broadcast_transaction_ptr)(&tx.into() as *const _)
77+
}
78+
}
79+
80+
#[repr(C)]
81+
pub enum FFIConfirmationTarget {
82+
/// We are happy with this transaction confirming slowly when feerate drops some.
83+
Background,
84+
/// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine.
85+
Normal,
86+
/// We'd like this transaction to confirm in the next few blocks.
87+
HighPriority,
88+
}
89+
90+
impl From<ConfirmationTarget> for FFIConfirmationTarget {
91+
fn from(target: ConfirmationTarget) -> FFIConfirmationTarget {
92+
match target {
93+
ConfirmationTarget::Background => FFIConfirmationTarget::Background,
94+
ConfirmationTarget::Normal => FFIConfirmationTarget::Normal,
95+
ConfirmationTarget::HighPriority => FFIConfirmationTarget::HighPriority,
96+
}
7697
}
7798
}
7899

79100
#[repr(C)]
80101
pub struct FFIFeeEstimator {
81-
get_est_sat_per_1000_weight_ptr: extern "cdecl" fn (&Self, ConfirmationTarget) -> u64,
102+
get_est_sat_per_1000_weight_ptr: extern "cdecl" fn (&Self, FFIConfirmationTarget) -> u64,
82103
}
83104

84105
impl FeeEstimator for FFIFeeEstimator {
85106
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u64 {
86-
(self.get_est_sat_per_1000_weight_ptr)(self, confirmation_target)
107+
(self.get_est_sat_per_1000_weight_ptr)(self, confirmation_target.into())
87108
}
88109
}
89110

@@ -104,13 +125,119 @@ impl FFINetwork {
104125
}
105126
}
106127

128+
#[derive(Debug)]
129+
#[repr(C)]
130+
pub enum FFILogLevel {
131+
///Designates logger being silent
132+
Off,
133+
/// Designates very serious errors
134+
Error,
135+
/// Designates hazardous situations
136+
Warn,
137+
/// Designates useful information
138+
Info,
139+
/// Designates lower priority information
140+
Debug,
141+
/// Designates very low priority, often extremely verbose, information
142+
Trace,
143+
}
144+
145+
impl From<Level> for FFILogLevel {
146+
fn from(level: Level) -> FFILogLevel {
147+
match level {
148+
Level::Off => FFILogLevel::Off,
149+
Level::Error => FFILogLevel::Error,
150+
Level::Warn => FFILogLevel::Warn,
151+
Level::Info => FFILogLevel::Info,
152+
Level::Debug => FFILogLevel::Debug,
153+
Level::Trace => FFILogLevel::Trace
154+
}
155+
}
156+
}
157+
158+
#[repr(C)]
159+
pub struct FFILogRecord {
160+
/// The verbosity level of the message.
161+
pub level: FFILogLevel,
162+
/// The message body.
163+
pub args: CString,
164+
/// The module path of the message.
165+
pub module_path: CString,
166+
/// The source file containing the message.
167+
pub file: CString,
168+
/// The line containing the message.
169+
pub line: u32,
170+
}
171+
172+
173+
impl<'a> From<Record<'a>> for FFILogRecord {
174+
fn from(rec: Record<'a>) -> Self {
175+
let args = CString::new(std::fmt::format(rec.args)).unwrap_or(CString::new("Record.args contains null char in the middle").unwrap());
176+
let module_path = CString::new(rec.module_path).unwrap_or(CString::new("Record.module_path contains null char in the middle").unwrap());
177+
let file = CString::new(rec.file).unwrap_or(CString::new("Record.file contains null char in the middle").unwrap());
178+
FFILogRecord {
179+
level: rec.level.into(),
180+
args: args,
181+
module_path: module_path,
182+
file: file,
183+
line: rec.line,
184+
}
185+
}
186+
}
187+
188+
impl<'a, 'b> From<&'a Record<'b>> for FFILogRecord {
189+
fn from(rec: &'a Record) -> Self {
190+
rec.into()
191+
}
192+
}
193+
107194
#[repr(C)]
108195
pub struct FFILogger {
109-
log_ptr: fn(&Self, &Record),
196+
log_ptr: extern "cdecl" fn(*const Self, *const FFILogRecord),
110197
}
111198

112199
impl Logger for FFILogger {
113200
fn log(&self, record: &Record) {
114-
(self.log_ptr)(self, record);
201+
let ffi_record: FFILogRecord = record.into();
202+
(self.log_ptr)(self, &ffi_record as *const _);
115203
}
116204
}
205+
206+
mod ChainWatchInterfaceFn {
207+
use super::*;
208+
pub type install_watch_tx_ptr = extern "cdecl" fn(*const FFIChainWatchInterface, *const FFISha256dHash, script_pub_key: *const FFIScript);
209+
pub type install_watch_outpoint_ptr = extern "cdecl" fn(*const FFIChainWatchInterface, outpoint: *const FFIOutPoint, out_script: *const FFIScript);
210+
pub type watch_all_txn_ptr = extern "cdecl" fn(*const FFIChainWatchInterface);
211+
pub type get_chain_utxo_ptr = extern "cdecl" fn(*const FFIChainWatchInterface, genesis_hash: *const FFISha256dHash, unspent_tx_output_identifier: u64, err: *mut ChainError, script: *mut FFITxOut);
212+
pub type filter_block_ptr = extern "cdecl" fn(*const FFIChainWatchInterface, *const FFIBlock);
213+
}
214+
215+
#[repr(C)]
216+
pub struct FFIChainWatchInterface {
217+
install_watch_tx_ptr: ChainWatchInterfaceFn::install_watch_tx_ptr,
218+
install_watch_outpoint_ptr: ChainWatchInterfaceFn::install_watch_tx_ptr,
219+
watch_all_txn_ptr: ChainWatchInterfaceFn::watch_all_txn_ptr,
220+
get_chain_utxo_ptr: ChainWatchInterfaceFn::get_chain_utxo_ptr,
221+
filter_block_ptr: ChainWatchInterfaceFn::filter_block_ptr,
222+
}
223+
224+
impl ChainWatchInterface for FFIChainWatchInterface {
225+
fn install_watch_tx(&self, txid: &Sha256dHash, script_pub_key: &Script) {
226+
(self.install_watch_tx_ptr)(self, &txid.into() as *const _, &script_pub_key.into() as *const _)
227+
}
228+
fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32), out_script: &Script) {
229+
unimplemented!("TODO")
230+
}
231+
fn watch_all_txn(&self) {
232+
unimplemented!()
233+
}
234+
fn get_chain_utxo(&self, genesis_hash: Sha256dHash, unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
235+
unimplemented!()
236+
}
237+
fn filter_block<'a>(&self, block: &'a Block) -> (Vec<&'a Transaction>, Vec<u32>) {
238+
unimplemented!()
239+
}
240+
fn reentered(&self) -> usize {
241+
unimplemented!()
242+
}
243+
}

bindings/src/adaptors/primitives.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use bitcoin::consensus::serialize;
2+
use secp256k1::constants::{SECRET_KEY_SIZE, PUBLIC_KEY_SIZE};
3+
use bitcoin::blockdata::script::Script;
4+
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
5+
use bitcoin::blockdata::block::Block;
6+
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
7+
8+
macro_rules! array_struct{
9+
($name:ident, $ty:ty) => {
10+
#[repr(C)]
11+
pub struct $name {
12+
ptr: *const $ty,
13+
len: u64,
14+
}
15+
}
16+
}
17+
18+
/// The length must be `secp256k1::constants::SECRET_KEY_SIZE` ,
19+
array_struct!(SecretKey, u8);
20+
21+
/// The length must be `secp256k1::constants::PUBLIC_KEY_SIZE` ,
22+
array_struct!(PublicKey, u8);
23+
24+
array_struct!(FFISha256dHash, u8);
25+
26+
impl From<&Sha256dHash> for FFISha256dHash {
27+
fn from(hash: &Sha256dHash) -> Self {
28+
let len = hash.len() as u64;
29+
let ptr = hash.as_ptr();
30+
FFISha256dHash { ptr: ptr, len: len, }
31+
}
32+
}
33+
34+
impl From<Sha256dHash> for FFISha256dHash {
35+
fn from(hash: Sha256dHash) -> Self {
36+
let len = hash.len() as u64; let ptr = hash.as_ptr();
37+
FFISha256dHash{ ptr: ptr, len: len, }
38+
}
39+
}
40+
41+
42+
array_struct!(FFIScript, u8);
43+
44+
impl From<Script> for FFIScript {
45+
fn from(script: Script) -> Self {
46+
let len = script.len() as u64;
47+
let ptr = script.as_bytes().as_ptr();
48+
FFIScript { ptr: ptr, len: len, }
49+
}
50+
}
51+
impl From<&Script> for FFIScript {
52+
fn from(script: &Script) -> Self {
53+
let len = script.len() as u64;
54+
let ptr = script.as_bytes().as_ptr();
55+
FFIScript { ptr: ptr, len: len, }
56+
}
57+
}
58+
59+
#[repr(C)]
60+
pub struct FFIOutPoint {
61+
pub txid: FFISha256dHash,
62+
pub index: u16,
63+
}
64+
65+
#[repr(C)]
66+
pub struct FFITxOut {
67+
value: u64,
68+
script_pubkey: FFIScript,
69+
}
70+
71+
array_struct!(FFITransaction, u8);
72+
impl From<Transaction> for FFITransaction {
73+
fn from(tx: Transaction) -> Self {
74+
let txb = serialize(&tx);
75+
FFITransaction {
76+
ptr: txb.as_ptr(),
77+
len: txb.len() as u64,
78+
}
79+
}
80+
}
81+
impl From<&Transaction> for FFITransaction {
82+
fn from(tx: &Transaction) -> Self {
83+
Self::from(tx.clone())
84+
}
85+
}
86+
87+
array_struct!(FFIBlock, u8);

bindings/src/broadcaster.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/// functions for managing broadcaster.
2+
/// Usually, you don't have to have a handler to the broadcaster in a wrapper side. Just create
3+
/// ChannelMonitor or ChannelManager and hold a reference to it.
4+
/// However, sometimes it is useful for testing.
5+
6+
use crate::adaptors::*;
7+
use crate::handle::{Ref, Out, HandleShared};
8+
use crate::error::FFIResult;
9+
10+
#[cfg(feature = "debug_assertions")]
11+
#[repr(C)]
12+
struct BroadcasterWrapper {
13+
broadcaster: Arc<FFIBroadCaster>,
14+
}
15+
16+
#[cfg(feature = "debug_assertions")]
17+
impl BroadcasterWrapper {
18+
pub fn broadcast(&self, tx: &tx) {
19+
self.broadcaster.broadcast_transaction(&tx)
20+
}
21+
}
22+
type FFIBroadCasterHandle<'a> = HandleShared<'a, FFIBroadCaster>;
23+
24+
ffi! {
25+
fn create_broadcaster(broadcast_transaction_ptr: Ref<BroadcasterFn::broadcast_transaction_ptr>, out: Out<FFIBroadCasterHandle>) -> FFIResult {
26+
let broadcast_transaction = unsafe_block!("" => *broadcast_transaction_ptr.as_ref());
27+
let broadcaster = FFIBroadCaster{ broadcast_transaction_ptr: broadcast_transaction };
28+
unsafe_block!("" => out.init(HandleShared::alloc(broadcaster)));
29+
FFIResult::ok()
30+
}
31+
32+
fn release_broadcaster(handle: FFIBroadCasterHandle) -> FFIResult {
33+
unsafe_block!("The upstream caller guarantees the handle will not be accessed after being freed" => FFIBroadCasterHandle::dealloc(handle, |mut handle| {
34+
FFIResult::ok()
35+
}))
36+
}
37+
}
38+
39+
#[cfg(feature = "debug_assertions")]
40+
ffi! {
41+
fn ffi_test_broadcaster(broadcaster_ptr: Ref<FFIBroadCaster>) -> FFIResult {
42+
let broadcaster = unsafe_block!("" => broadcaster_ptr.as_ref());
43+
let tx: Transaction = bitcoin::consensus::deserialize(&hex::decode("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700")?)?;
44+
broadcaster.broadcast_transaction(&tx);
45+
FFIResult::ok()
46+
}
47+
fn ffi_test_broadcaster_in_wrapper(broadcaster_ptr: Ref<FFIBroadCaster>, out: Out<BroadcasterWrapper>) -> FFIResult {
48+
let broadcaster = unsafe_block!("" => broadcaster_ptr.as_arc());
49+
let wrapper_raw = BroadcasterWrapper{ broadcaster: broadcaster };
50+
let tx: Transaction = bitcoin::consensus::deserialize(&hex::decode("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700")?)?;
51+
let wrapper = out.init(wrapper_raw);
52+
wrapper.broadcast(&tx);
53+
}
54+
55+
fn ffi_test_chainwatch_interface(chainwatcher_ptr: Ref<FFIChainWatchInterface>) -> FFIResult {
56+
let chainwatcher = unsafe_block!("" => chainwatcher_ptr.as_ref());
57+
// chainwatcher.install_watch_tx();
58+
FFIResult::ok()
59+
}
60+
}

bindings/src/chainwatcher.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use crate::adaptors::*;
2+
use crate::error::FFIResult;
3+
use crate::handle::{Ref};
4+
5+
ffi! {
6+
fn ffi_test_chainwatch_interface(chainwatcher_ptr: Ref<FFIChainWatchInterface>) -> FFIResult {
7+
let chainwatcher = unsafe_block!("" => chainwatcher_ptr.as_ref());
8+
// chainwatcher.install_watch_tx();
9+
FFIResult::ok()
10+
}
11+
}

0 commit comments

Comments
 (0)