Skip to content

Commit 3f0cf77

Browse files
committed
Generate UniFFI scaffolding
We generate the scaffolding from an UDL file and include it in `lib.rs`. Furthermore, we add a bindings generation shell script for convenience.
1 parent de7fc2a commit 3f0cf77

File tree

12 files changed

+709
-70
lines changed

12 files changed

+709
-70
lines changed

Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ description = "A ready-to-go node implementation built using LDK."
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[lib]
12+
crate-type = ["staticlib", "cdylib"]
13+
name = "ldk_node"
14+
15+
[[bin]]
16+
name = "uniffi-bindgen"
17+
path = "uniffi-bindgen.rs"
18+
19+
[profile.release-smaller]
20+
inherits = "release"
21+
opt-level = 'z' # Optimize for size.
22+
lto = true # Enable Link Time Optimization
23+
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
24+
panic = 'abort' # Abort on panic
25+
strip = true # Strip symbols from binary*
26+
1127
[dependencies]
1228
#lightning = { version = "0.0.114", features = ["max_level_trace", "std"] }
1329
#lightning-invoice = { version = "0.22" }
@@ -53,13 +69,18 @@ serde_json = { version = "1.0" }
5369
tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "sync" ] }
5470
esplora-client = { version = "0.4", default-features = false }
5571
libc = "0.2"
72+
uniffi = { version = "0.23.0", features = ["build"] }
5673

5774
[dev-dependencies]
5875
electrsd = { version = "0.22.0", features = ["legacy", "esplora_a33e97e1", "bitcoind_23_0"] }
5976
electrum-client = "0.12.0"
6077
proptest = "1.0.0"
6178
regex = "1.5.6"
6279

80+
[build-dependencies]
81+
uniffi = { version = "0.23.0", features = ["build", "cli"] }
82+
83+
6384
[profile.release]
6485
panic = "abort"
6586

bindings/ldk_node.udl

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
namespace ldk_node {
2+
};
3+
4+
dictionary Config {
5+
string storage_dir_path;
6+
string esplora_server_url;
7+
Network network;
8+
SocketAddr? listening_address;
9+
u32 default_cltv_expiry_delta;
10+
};
11+
12+
interface Builder {
13+
constructor();
14+
[Name=from_config]
15+
constructor(Config config);
16+
Node build();
17+
};
18+
19+
interface Node {
20+
[Throws=NodeError]
21+
void start();
22+
[Throws=NodeError]
23+
void stop();
24+
[Throws=NodeError]
25+
void sync_wallets();
26+
Event next_event();
27+
void event_handled();
28+
PublicKey node_id();
29+
[Throws=NodeError]
30+
Address new_funding_address();
31+
[Throws=NodeError]
32+
u64 spendable_onchain_balance_sats();
33+
[Throws=NodeError]
34+
u64 total_onchain_balance_sats();
35+
[Throws=NodeError]
36+
void connect(PublicKey node_id, SocketAddr address, boolean permanently);
37+
[Throws=NodeError]
38+
void disconnect([ByRef]PublicKey node_id);
39+
[Throws=NodeError]
40+
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
41+
[Throws=NodeError]
42+
void close_channel([ByRef]ChannelId channel_id, [ByRef]PublicKey counterparty_node_id);
43+
[Throws=NodeError]
44+
PaymentHash send_payment([ByRef]Invoice invoice);
45+
[Throws=NodeError]
46+
PaymentHash send_payment_using_amount([ByRef]Invoice invoice, u64 amount_msat);
47+
[Throws=NodeError]
48+
PaymentHash send_spontaneous_payment(u64 amount_msat, [ByRef]PublicKey node_id);
49+
[Throws=NodeError]
50+
Invoice receive_payment(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
51+
[Throws=NodeError]
52+
Invoice receive_variable_amount_payment([ByRef]string description, u32 expiry_secs);
53+
PaymentDetails? payment([ByRef]PaymentHash payment_hash);
54+
};
55+
56+
[Error]
57+
enum NodeError {
58+
"AlreadyRunning",
59+
"NotRunning",
60+
"FundingTxCreationFailed",
61+
"ConnectionFailed",
62+
"AddressInvalid",
63+
"PublicKeyInvalid",
64+
"PaymentHashInvalid",
65+
"PaymentPreimageInvalid",
66+
"PaymentSecretInvalid",
67+
"NonUniquePaymentHash",
68+
"InvalidAmount",
69+
"InvalidInvoice",
70+
"InvoiceCreationFailed",
71+
"InsufficientFunds",
72+
"PaymentFailed",
73+
"ChannelIdInvalid",
74+
"NetworkInvalid",
75+
"PeerInfoParseFailed",
76+
"ChannelCreationFailed",
77+
"ChannelClosingFailed",
78+
"PersistenceFailed",
79+
"WalletOperationFailed",
80+
"WalletSigningFailed",
81+
"TxSyncFailed",
82+
};
83+
84+
[Enum]
85+
interface Event {
86+
PaymentSuccessful( PaymentHash payment_hash );
87+
PaymentFailed( PaymentHash payment_hash );
88+
PaymentReceived( PaymentHash payment_hash, u64 amount_msat);
89+
ChannelPending ( ChannelId channel_id, UserChannelId user_channel_id, ChannelId former_temporary_channel_id, PublicKey counterparty_node_id, OutPoint funding_txo );
90+
ChannelReady ( ChannelId channel_id, UserChannelId user_channel_id );
91+
ChannelClosed ( ChannelId channel_id, UserChannelId user_channel_id );
92+
};
93+
94+
enum PaymentDirection {
95+
"Inbound",
96+
"Outbound",
97+
};
98+
99+
enum PaymentStatus {
100+
"Pending",
101+
"Succeeded",
102+
"Failed",
103+
};
104+
105+
dictionary PaymentDetails {
106+
PaymentHash hash;
107+
PaymentPreimage? preimage;
108+
PaymentSecret? secret;
109+
u64? amount_msat;
110+
PaymentDirection direction;
111+
PaymentStatus status;
112+
};
113+
114+
dictionary OutPoint {
115+
Txid txid;
116+
u32 vout;
117+
};
118+
119+
[Custom]
120+
typedef string Txid;
121+
122+
[Custom]
123+
typedef string SocketAddr;
124+
125+
[Custom]
126+
typedef string PublicKey;
127+
128+
[Custom]
129+
typedef string Address;
130+
131+
[Custom]
132+
typedef string Invoice;
133+
134+
[Custom]
135+
typedef string PaymentHash;
136+
137+
[Custom]
138+
typedef string PaymentPreimage;
139+
140+
[Custom]
141+
typedef string PaymentSecret;
142+
143+
[Custom]
144+
typedef string ChannelId;
145+
146+
[Custom]
147+
typedef string UserChannelId;
148+
149+
[Custom]
150+
typedef string Network;

build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
uniffi::generate_scaffolding("bindings/ldk_node.udl").unwrap();
3+
}

scripts/uniffi_bindgen_generate.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#!/bin/bash

src/error.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ pub enum Error {
1111
FundingTxCreationFailed,
1212
/// A network connection has been closed.
1313
ConnectionFailed,
14+
/// The given address is invalid.
15+
AddressInvalid,
16+
/// The given public key is invalid.
17+
PublicKeyInvalid,
18+
/// The given payment hash is invalid.
19+
PaymentHashInvalid,
20+
/// The given payment preimage is invalid.
21+
PaymentPreimageInvalid,
22+
/// The given payment secret is invalid.
23+
PaymentSecretInvalid,
1424
/// Payment of the given invoice has already been intiated.
1525
NonUniquePaymentHash,
1626
/// The given amount is invalid.
@@ -23,6 +33,10 @@ pub enum Error {
2333
InsufficientFunds,
2434
/// An attempted payment has failed.
2535
PaymentFailed,
36+
/// The given channel ID is invalid.
37+
ChannelIdInvalid,
38+
/// The given network is invalid.
39+
NetworkInvalid,
2640
/// A given peer info could not be parsed.
2741
PeerInfoParseFailed,
2842
/// A channel could not be opened.
@@ -44,10 +58,13 @@ impl fmt::Display for Error {
4458
match *self {
4559
Self::AlreadyRunning => write!(f, "Node is already running."),
4660
Self::NotRunning => write!(f, "Node is not running."),
47-
Self::FundingTxCreationFailed => {
48-
write!(f, "Funding transaction could not be created.")
49-
}
61+
Self::FundingTxCreationFailed => write!(f, "Funding transaction could not be created."),
5062
Self::ConnectionFailed => write!(f, "Network connection closed."),
63+
Self::AddressInvalid => write!(f, "The given address is invalid."),
64+
Self::PublicKeyInvalid => write!(f, "The given public key is invalid."),
65+
Self::PaymentHashInvalid => write!(f, "The given payment hash is invalid."),
66+
Self::PaymentPreimageInvalid => write!(f, "The given payment preimage is invalid."),
67+
Self::PaymentSecretInvalid => write!(f, "The given payment secret is invalid."),
5168
Self::NonUniquePaymentHash => write!(f, "An invoice must not get payed twice."),
5269
Self::InvalidAmount => write!(f, "The given amount is invalid."),
5370
Self::InvalidInvoice => write!(f, "The given invoice is invalid."),
@@ -56,6 +73,8 @@ impl fmt::Display for Error {
5673
write!(f, "There are insufficient funds to complete the given operation.")
5774
}
5875
Self::PaymentFailed => write!(f, "Failed to send the given payment."),
76+
Self::ChannelIdInvalid => write!(f, "The given channel ID is invalid."),
77+
Self::NetworkInvalid => write!(f, "The given network is invalid."),
5978
Self::PeerInfoParseFailed => write!(f, "Failed to parse the given peer information."),
6079
Self::ChannelCreationFailed => write!(f, "Failed to create channel."),
6180
Self::ChannelClosingFailed => write!(f, "Failed to close channel."),

src/event.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{hex_utils, ChannelManager, Config, Error, KeysManager, NetworkGraph, Wallet};
1+
use crate::{
2+
hex_utils, ChannelId, ChannelManager, Config, Error, KeysManager, NetworkGraph, UserChannelId,
3+
Wallet,
4+
};
25

36
use crate::payment_store::{
47
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentStatus, PaymentStore,
@@ -52,11 +55,11 @@ pub enum Event {
5255
/// A channel has been created and is pending confirmation on-chain.
5356
ChannelPending {
5457
/// The `channel_id` of the channel.
55-
channel_id: [u8; 32],
58+
channel_id: ChannelId,
5659
/// The `user_channel_id` of the channel.
57-
user_channel_id: u128,
60+
user_channel_id: UserChannelId,
5861
/// The `temporary_channel_id` this channel used to be known by during channel establishment.
59-
former_temporary_channel_id: [u8; 32],
62+
former_temporary_channel_id: ChannelId,
6063
/// The `node_id` of the channel counterparty.
6164
counterparty_node_id: PublicKey,
6265
/// The outpoint of the channel's funding transaction.
@@ -65,16 +68,16 @@ pub enum Event {
6568
/// A channel is ready to be used.
6669
ChannelReady {
6770
/// The `channel_id` of the channel.
68-
channel_id: [u8; 32],
71+
channel_id: ChannelId,
6972
/// The `user_channel_id` of the channel.
70-
user_channel_id: u128,
73+
user_channel_id: UserChannelId,
7174
},
7275
/// A channel has been closed.
7376
ChannelClosed {
7477
/// The `channel_id` of the channel.
75-
channel_id: [u8; 32],
78+
channel_id: ChannelId,
7679
/// The `user_channel_id` of the channel.
77-
user_channel_id: u128,
80+
user_channel_id: UserChannelId,
7881
},
7982
}
8083

@@ -642,9 +645,11 @@ where
642645
);
643646
self.event_queue
644647
.add_event(Event::ChannelPending {
645-
channel_id,
646-
user_channel_id,
647-
former_temporary_channel_id: former_temporary_channel_id.unwrap(),
648+
channel_id: ChannelId(channel_id),
649+
user_channel_id: UserChannelId(user_channel_id),
650+
former_temporary_channel_id: ChannelId(
651+
former_temporary_channel_id.unwrap(),
652+
),
648653
counterparty_node_id,
649654
funding_txo,
650655
})
@@ -660,7 +665,10 @@ where
660665
counterparty_node_id,
661666
);
662667
self.event_queue
663-
.add_event(Event::ChannelReady { channel_id, user_channel_id })
668+
.add_event(Event::ChannelReady {
669+
channel_id: ChannelId(channel_id),
670+
user_channel_id: UserChannelId(user_channel_id),
671+
})
664672
.expect("Failed to push to event queue");
665673
}
666674
LdkEvent::ChannelClosed { channel_id, reason, user_channel_id } => {
@@ -671,7 +679,10 @@ where
671679
reason
672680
);
673681
self.event_queue
674-
.add_event(Event::ChannelClosed { channel_id, user_channel_id })
682+
.add_event(Event::ChannelClosed {
683+
channel_id: ChannelId(channel_id),
684+
user_channel_id: UserChannelId(user_channel_id),
685+
})
675686
.expect("Failed to push to event queue");
676687
}
677688
LdkEvent::DiscardFunding { .. } => {}
@@ -691,7 +702,10 @@ mod tests {
691702
let logger = Arc::new(TestLogger::new());
692703
let event_queue = EventQueue::new(Arc::clone(&store), Arc::clone(&logger));
693704

694-
let expected_event = Event::ChannelReady { channel_id: [23u8; 32], user_channel_id: 2323 };
705+
let expected_event = Event::ChannelReady {
706+
channel_id: ChannelId([23u8; 32]),
707+
user_channel_id: UserChannelId(2323),
708+
};
695709
event_queue.add_event(expected_event.clone()).unwrap();
696710
assert!(store.get_and_clear_did_persist());
697711

0 commit comments

Comments
 (0)