Skip to content

Commit 1c6d9d4

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 f83a5c6 commit 1c6d9d4

File tree

12 files changed

+706
-54
lines changed

12 files changed

+706
-54
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.115", features = ["max_level_trace", "std"] }
1329
lightning-invoice = { version = "0.23" }
@@ -46,13 +62,18 @@ serde_json = { version = "1.0" }
4662
tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "sync" ] }
4763
esplora-client = { version = "0.4", default-features = false }
4864
libc = "0.2"
65+
uniffi = { version = "0.23.0", features = ["build"] }
4966

5067
[dev-dependencies]
5168
electrsd = { version = "0.22.0", features = ["legacy", "esplora_a33e97e1", "bitcoind_23_0"] }
5269
electrum-client = "0.12.0"
5370
proptest = "1.0.0"
5471
regex = "1.5.6"
5572

73+
[build-dependencies]
74+
uniffi = { version = "0.23.0", features = ["build", "cli"] }
75+
76+
5677
[profile.release]
5778
panic = "abort"
5879

bindings/ldk_node.udl

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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+
Event next_event();
25+
void event_handled();
26+
PublicKey node_id();
27+
SocketAddr? listening_address();
28+
[Throws=NodeError]
29+
Address new_funding_address();
30+
[Throws=NodeError]
31+
Txid send_to_onchain_address([ByRef]Address address, u64 amount_msat);
32+
[Throws=NodeError]
33+
Txid send_all_to_onchain_address([ByRef]Address address);
34+
[Throws=NodeError]
35+
u64 spendable_onchain_balance_sats();
36+
[Throws=NodeError]
37+
u64 total_onchain_balance_sats();
38+
[Throws=NodeError]
39+
void connect(PublicKey node_id, SocketAddr address, boolean permanently);
40+
[Throws=NodeError]
41+
void disconnect([ByRef]PublicKey node_id);
42+
[Throws=NodeError]
43+
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
44+
[Throws=NodeError]
45+
void close_channel([ByRef]ChannelId channel_id, [ByRef]PublicKey counterparty_node_id);
46+
[Throws=NodeError]
47+
void sync_wallets();
48+
[Throws=NodeError]
49+
PaymentHash send_payment([ByRef]Invoice invoice);
50+
[Throws=NodeError]
51+
PaymentHash send_payment_using_amount([ByRef]Invoice invoice, u64 amount_msat);
52+
[Throws=NodeError]
53+
PaymentHash send_spontaneous_payment(u64 amount_msat, [ByRef]PublicKey node_id);
54+
[Throws=NodeError]
55+
Invoice receive_payment(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
56+
[Throws=NodeError]
57+
Invoice receive_variable_amount_payment([ByRef]string description, u32 expiry_secs);
58+
PaymentDetails? payment([ByRef]PaymentHash payment_hash);
59+
[Throws=NodeError]
60+
boolean remove_payment([ByRef]PaymentHash payment_hash);
61+
};
62+
63+
[Error]
64+
enum NodeError {
65+
"AlreadyRunning",
66+
"NotRunning",
67+
"OnchainTxCreationFailed",
68+
"ConnectionFailed",
69+
"AddressInvalid",
70+
"PublicKeyInvalid",
71+
"PaymentHashInvalid",
72+
"PaymentPreimageInvalid",
73+
"PaymentSecretInvalid",
74+
"NonUniquePaymentHash",
75+
"InvalidAmount",
76+
"InvalidInvoice",
77+
"InvoiceCreationFailed",
78+
"InsufficientFunds",
79+
"PaymentFailed",
80+
"ChannelIdInvalid",
81+
"NetworkInvalid",
82+
"PeerInfoParseFailed",
83+
"ChannelCreationFailed",
84+
"ChannelClosingFailed",
85+
"PersistenceFailed",
86+
"WalletOperationFailed",
87+
"WalletSigningFailed",
88+
"TxSyncFailed",
89+
};
90+
91+
[Enum]
92+
interface Event {
93+
PaymentSuccessful( PaymentHash payment_hash );
94+
PaymentFailed( PaymentHash payment_hash );
95+
PaymentReceived( PaymentHash payment_hash, u64 amount_msat);
96+
ChannelPending ( ChannelId channel_id, UserChannelId user_channel_id, ChannelId former_temporary_channel_id, PublicKey counterparty_node_id, OutPoint funding_txo );
97+
ChannelReady ( ChannelId channel_id, UserChannelId user_channel_id );
98+
ChannelClosed ( ChannelId channel_id, UserChannelId user_channel_id );
99+
};
100+
101+
enum PaymentDirection {
102+
"Inbound",
103+
"Outbound",
104+
};
105+
106+
enum PaymentStatus {
107+
"Pending",
108+
"Succeeded",
109+
"Failed",
110+
};
111+
112+
dictionary PaymentDetails {
113+
PaymentHash hash;
114+
PaymentPreimage? preimage;
115+
PaymentSecret? secret;
116+
u64? amount_msat;
117+
PaymentDirection direction;
118+
PaymentStatus status;
119+
};
120+
121+
dictionary OutPoint {
122+
Txid txid;
123+
u32 vout;
124+
};
125+
126+
[Custom]
127+
typedef string Txid;
128+
129+
[Custom]
130+
typedef string SocketAddr;
131+
132+
[Custom]
133+
typedef string PublicKey;
134+
135+
[Custom]
136+
typedef string Address;
137+
138+
[Custom]
139+
typedef string Invoice;
140+
141+
[Custom]
142+
typedef string PaymentHash;
143+
144+
[Custom]
145+
typedef string PaymentPreimage;
146+
147+
[Custom]
148+
typedef string PaymentSecret;
149+
150+
[Custom]
151+
typedef string ChannelId;
152+
153+
[Custom]
154+
typedef string UserChannelId;
155+
156+
[Custom]
157+
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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ pub enum Error {
1111
OnchainTxCreationFailed,
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.
@@ -48,6 +62,11 @@ impl fmt::Display for Error {
4862
write!(f, "On-chain transaction could not be created.")
4963
}
5064
Self::ConnectionFailed => write!(f, "Network connection closed."),
65+
Self::AddressInvalid => write!(f, "The given address is invalid."),
66+
Self::PublicKeyInvalid => write!(f, "The given public key is invalid."),
67+
Self::PaymentHashInvalid => write!(f, "The given payment hash is invalid."),
68+
Self::PaymentPreimageInvalid => write!(f, "The given payment preimage is invalid."),
69+
Self::PaymentSecretInvalid => write!(f, "The given payment secret is invalid."),
5170
Self::NonUniquePaymentHash => write!(f, "An invoice must not get payed twice."),
5271
Self::InvalidAmount => write!(f, "The given amount is invalid."),
5372
Self::InvalidInvoice => write!(f, "The given invoice is invalid."),
@@ -56,6 +75,8 @@ impl fmt::Display for Error {
5675
write!(f, "There are insufficient funds to complete the given operation.")
5776
}
5877
Self::PaymentFailed => write!(f, "Failed to send the given payment."),
78+
Self::ChannelIdInvalid => write!(f, "The given channel ID is invalid."),
79+
Self::NetworkInvalid => write!(f, "The given network is invalid."),
5980
Self::PeerInfoParseFailed => write!(f, "Failed to parse the given peer information."),
6081
Self::ChannelCreationFailed => write!(f, "Failed to create channel."),
6182
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,
@@ -51,11 +54,11 @@ pub enum Event {
5154
/// A channel has been created and is pending confirmation on-chain.
5255
ChannelPending {
5356
/// The `channel_id` of the channel.
54-
channel_id: [u8; 32],
57+
channel_id: ChannelId,
5558
/// The `user_channel_id` of the channel.
56-
user_channel_id: u128,
59+
user_channel_id: UserChannelId,
5760
/// The `temporary_channel_id` this channel used to be known by during channel establishment.
58-
former_temporary_channel_id: [u8; 32],
61+
former_temporary_channel_id: ChannelId,
5962
/// The `node_id` of the channel counterparty.
6063
counterparty_node_id: PublicKey,
6164
/// The outpoint of the channel's funding transaction.
@@ -64,16 +67,16 @@ pub enum Event {
6467
/// A channel is ready to be used.
6568
ChannelReady {
6669
/// The `channel_id` of the channel.
67-
channel_id: [u8; 32],
70+
channel_id: ChannelId,
6871
/// The `user_channel_id` of the channel.
69-
user_channel_id: u128,
72+
user_channel_id: UserChannelId,
7073
},
7174
/// A channel has been closed.
7275
ChannelClosed {
7376
/// The `channel_id` of the channel.
74-
channel_id: [u8; 32],
77+
channel_id: ChannelId,
7578
/// The `user_channel_id` of the channel.
76-
user_channel_id: u128,
79+
user_channel_id: UserChannelId,
7780
},
7881
}
7982

@@ -641,9 +644,11 @@ where
641644
);
642645
self.event_queue
643646
.add_event(Event::ChannelPending {
644-
channel_id,
645-
user_channel_id,
646-
former_temporary_channel_id: former_temporary_channel_id.unwrap(),
647+
channel_id: ChannelId(channel_id),
648+
user_channel_id: UserChannelId(user_channel_id),
649+
former_temporary_channel_id: ChannelId(
650+
former_temporary_channel_id.unwrap(),
651+
),
647652
counterparty_node_id,
648653
funding_txo,
649654
})
@@ -659,7 +664,10 @@ where
659664
counterparty_node_id,
660665
);
661666
self.event_queue
662-
.add_event(Event::ChannelReady { channel_id, user_channel_id })
667+
.add_event(Event::ChannelReady {
668+
channel_id: ChannelId(channel_id),
669+
user_channel_id: UserChannelId(user_channel_id),
670+
})
663671
.expect("Failed to push to event queue");
664672
}
665673
LdkEvent::ChannelClosed { channel_id, reason, user_channel_id } => {
@@ -670,7 +678,10 @@ where
670678
reason
671679
);
672680
self.event_queue
673-
.add_event(Event::ChannelClosed { channel_id, user_channel_id })
681+
.add_event(Event::ChannelClosed {
682+
channel_id: ChannelId(channel_id),
683+
user_channel_id: UserChannelId(user_channel_id),
684+
})
674685
.expect("Failed to push to event queue");
675686
}
676687
LdkEvent::DiscardFunding { .. } => {}
@@ -690,7 +701,10 @@ mod tests {
690701
let logger = Arc::new(TestLogger::new());
691702
let event_queue = EventQueue::new(Arc::clone(&store), Arc::clone(&logger));
692703

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

0 commit comments

Comments
 (0)