8 #include "include/lightningpp.hpp"
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
25 const uint8_t valid_node_announcement[] = {
26 0x94, 0xe4, 0xf5, 0x61, 0x41, 0x24, 0x7d, 0x90, 0x23, 0xa0, 0xc8, 0x34, 0x8c, 0xc4, 0xca, 0x51,
27 0xd8, 0x17, 0x59, 0xff, 0x7d, 0xac, 0x8c, 0x9b, 0x63, 0x29, 0x1c, 0xe6, 0x12, 0x12, 0x93, 0xbd,
28 0x66, 0x4d, 0x6b, 0x9c, 0xfb, 0x35, 0xda, 0x16, 0x06, 0x3d, 0xf0, 0x8f, 0x8a, 0x39, 0x99, 0xa2,
29 0xf2, 0x5d, 0x12, 0x0f, 0x2b, 0x42, 0x1b, 0x8b, 0x9a, 0xfe, 0x33, 0x0c, 0xeb, 0x33, 0x5e, 0x52,
30 0xee, 0x99, 0xa1, 0x07, 0x06, 0xed, 0xf8, 0x48, 0x7a, 0xc6, 0xe5, 0xf5, 0x5e, 0x01, 0x3a, 0x41,
31 0x2f, 0x18, 0x94, 0x8a, 0x3b, 0x0a, 0x52, 0x3f, 0xbf, 0x61, 0xa9, 0xc5, 0x4f, 0x70, 0xee, 0xb8,
32 0x79, 0x23, 0xbb, 0x1a, 0x44, 0x7d, 0x91, 0xe6, 0x2a, 0xbc, 0xa1, 0x07, 0xbc, 0x65, 0x3b, 0x02,
33 0xd9, 0x1d, 0xb2, 0xf2, 0x3a, 0xcb, 0x75, 0x79, 0xc6, 0x66, 0xd8, 0xc1, 0x71, 0x29, 0xdf, 0x04,
34 0x60, 0xf4, 0xbf, 0x07, 0x7b, 0xb9, 0xc2, 0x11, 0x94, 0x6a, 0x28, 0xc2, 0xdd, 0xd8, 0x7b, 0x44,
35 0x8f, 0x08, 0xe3, 0xc8, 0xd8, 0xf4, 0x81, 0xb0, 0x9f, 0x94, 0xcb, 0xc8, 0xc1, 0x3c, 0xc2, 0x6e,
36 0x31, 0x26, 0xfc, 0x33, 0x16, 0x3b, 0xe0, 0xde, 0xa1, 0x16, 0x21, 0x9f, 0x89, 0xdd, 0x97, 0xa4,
37 0x41, 0xf2, 0x9f, 0x19, 0xb1, 0xae, 0x82, 0xf7, 0x85, 0x9a, 0xb7, 0x8f, 0xb7, 0x52, 0x7a, 0x72,
38 0xf1, 0x5e, 0x89, 0xe1, 0x8a, 0xcd, 0x40, 0xb5, 0x8e, 0xc3, 0xca, 0x42, 0x76, 0xa3, 0x6e, 0x1b,
39 0xf4, 0x87, 0x35, 0x30, 0x58, 0x43, 0x04, 0xd9, 0x2c, 0x50, 0x54, 0x55, 0x47, 0x6f, 0x70, 0x9b,
40 0x42, 0x1f, 0x91, 0xfc, 0xa1, 0xdb, 0x72, 0x53, 0x96, 0xc8, 0xe5, 0xcd, 0x0e, 0xcb, 0xa0, 0xfe,
41 0x6b, 0x08, 0x77, 0x48, 0xb7, 0xad, 0x4a, 0x69, 0x7c, 0xdc, 0xd8, 0x04, 0x28, 0x35, 0x9b, 0x73,
42 0x00, 0x00, 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce,
43 0xc3, 0xae, 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, 0x01, 0xea, 0x33, 0x09, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5b, 0xe5, 0xe9, 0x47, 0x82,
45 0x09, 0x67, 0x4a, 0x96, 0xe6, 0x0f, 0x1f, 0x03, 0x7f, 0x61, 0x76, 0x54, 0x0f, 0xd0, 0x01, 0xfa,
46 0x1d, 0x64, 0x69, 0x47, 0x70, 0xc5, 0x6a, 0x77, 0x09, 0xc4, 0x2c, 0x03, 0x5c, 0x4e, 0x0d, 0xec,
47 0x72, 0x15, 0xe2, 0x68, 0x33, 0x93, 0x87, 0x30, 0xe5, 0xe5, 0x05, 0xaa, 0x62, 0x50, 0x4d, 0xa8,
48 0x5b, 0xa5, 0x71, 0x06, 0xa4, 0x6b, 0x5a, 0x24, 0x04, 0xfc, 0x9d, 0x8e, 0x02, 0xba, 0x72, 0xa6,
49 0xe8, 0xba, 0x53, 0xe8, 0xb9, 0x71, 0xad, 0x0c, 0x98, 0x23, 0x96, 0x8a, 0xef, 0x4d, 0x78, 0xce,
50 0x8a, 0xf2, 0x55, 0xab, 0x43, 0xdf, 0xf8, 0x30, 0x03, 0xc9, 0x02, 0xfb, 0x8d, 0x02, 0x16, 0x34,
51 0x5b, 0xf8, 0x31, 0x16, 0x4a, 0x03, 0x75, 0x8e, 0xae, 0xa5, 0xe8, 0xb6, 0x6f, 0xee, 0x2b, 0xe7,
52 0x71, 0x0b, 0x8f, 0x19, 0x0e, 0xe8, 0x80, 0x24, 0x90, 0x32, 0xa2, 0x9e, 0xd6, 0x6e
55 // A simple block containing only one transaction (which is the channel-open transaction for the
56 // channel we'll create). This was originally created by printing additional data in a simple
57 // rust-lightning unit test.
59 // Note that the merkle root is incorrect, but it isn't ever checked by LDK, so should be fine.
60 const uint8_t channel_open_block[] = {
61 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0xa2, 0x47, 0xd2, 0xf8, 0xd4, 0xe0, 0x6a, 0x3f, 0xf9, 0x7a, 0x9a, 0x34,
64 0xbb, 0xa9, 0x96, 0xde, 0x63, 0x84, 0x5a, 0xce, 0xcf, 0x98, 0xb8, 0xbb, 0x75, 0x4c, 0x4f, 0x7d,
65 0xee, 0x4c, 0xa9, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x01, // transaction count
67 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x01, 0x40, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0xc5, 0x1c, 0xad, 0x5e,
71 0x51, 0x11, 0xb0, 0x11, 0xa1, 0x14, 0xf4, 0xda, 0x02, 0x3d, 0xbc, 0xc1, 0x44, 0x3c, 0x67, 0x31,
72 0xec, 0x6f, 0x10, 0x2f, 0x89, 0xc1, 0x05, 0x80, 0xfe, 0xfc, 0xd6, 0xc7, 0x01, 0x00, 0x00, 0x00,
76 // The first transaction in the block is header (80 bytes) + transaction count (1 byte) into the block data.
77 const uint8_t channel_open_txid[] = {
78 0x7a, 0x14, 0x8f, 0xb4, 0x08, 0x49, 0x9b, 0x51, 0x2e, 0xff, 0xf9, 0x46, 0x73, 0xca, 0xc6, 0x48,
79 0xfd, 0x95, 0x0e, 0x72, 0xd4, 0xd3, 0xdb, 0x79, 0xc9, 0x20, 0xed, 0x83, 0xb2, 0xde, 0xed, 0x41,
82 // Two blocks built on top of channel_open_block:
83 const uint8_t block_1[81] = {
84 0x01, 0x00, 0x00, 0x00, 0x0c, 0x7a, 0xc2, 0xdc, 0x08, 0xaf, 0x40, 0x7d, 0x58, 0x81, 0x9b, 0x44,
85 0xc7, 0xe0, 0x0f, 0x78, 0xc0, 0xd1, 0x01, 0xa2, 0x03, 0x16, 0x4a, 0x8d, 0x92, 0x66, 0x4e, 0xaf,
86 0x7f, 0xfc, 0x6e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, // transaction count
91 const uint8_t block_2[81] = {
92 0x01, 0x00, 0x00, 0x00, 0x36, 0x0b, 0xf5, 0x46, 0x4a, 0xc7, 0x26, 0x4c, 0x4b, 0x36, 0xa6, 0x9d,
93 0x0e, 0xf0, 0x14, 0xfb, 0x8a, 0xcb, 0x20, 0x84, 0x18, 0xf3, 0xaa, 0x77, 0x32, 0x2d, 0xf7, 0x48,
94 0x62, 0x92, 0xb1, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, // transaction count
100 void print_log(const void *this_arg, const LDKRecord *record) {
101 LDK::Str mod = Record_get_module_path(record);
102 LDK::Str str = Record_get_args(record);
103 printf("%p - %.*s:%d - %.*s\n", this_arg, (int)mod->len, mod->chars, Record_get_line(record), (int)str->len, str->chars);
106 uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) {
107 if (target == LDKConfirmationTarget_Background) {
112 // Note that we don't call _free() on target, but that's OK, its unitary
114 // We use the same fee estimator globally:
115 const LDKFeeEstimator fee_est {
117 .get_est_sat_per_1000_weight = get_fee,
121 static std::atomic_int num_txs_broadcasted(0);
122 void broadcast_tx(const void *this_arg, LDKTransaction tx) {
123 num_txs_broadcasted += 1;
125 Transaction_free(tx);
128 struct NodeMonitors {
130 std::vector<std::pair<LDK::OutPoint, LDK::ChannelMonitor>> mons;
133 void ConnectBlock(const uint8_t (*header)[80], uint32_t height, LDKCVec_C2Tuple_usizeTransactionZZ tx_data, LDKBroadcasterInterface broadcast, LDKFeeEstimator fee_est) {
134 std::unique_lock<std::mutex> l(mut);
135 for (auto& mon : mons) {
136 LDK::CVec_TransactionOutputsZ res = ChannelMonitor_block_connected(&mon.second, header, tx_data, height, broadcast, fee_est, *logger);
141 LDKChannelMonitorUpdateStatus add_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, LDKChannelMonitor monitor_arg) {
142 // First bind the args to C++ objects so they auto-free
143 LDK::ChannelMonitor mon(std::move(monitor_arg));
144 LDK::OutPoint funding_txo(std::move(funding_txo_arg));
146 NodeMonitors* arg = (NodeMonitors*) this_arg;
147 std::unique_lock<std::mutex> l(arg->mut);
149 arg->mons.push_back(std::make_pair(std::move(funding_txo), std::move(mon)));
150 return ChannelMonitorUpdateStatus_completed();
152 static std::atomic_int mons_updated(0);
153 LDKChannelMonitorUpdateStatus update_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, const LDKChannelMonitorUpdate *update) {
154 // First bind the args to C++ objects so they auto-free
155 LDK::OutPoint funding_txo(std::move(funding_txo_arg));
157 NodeMonitors* arg = (NodeMonitors*) this_arg;
158 std::unique_lock<std::mutex> l(arg->mut);
160 bool updated = false;
161 for (auto& mon : arg->mons) {
162 if (OutPoint_get_index(&mon.first) == OutPoint_get_index(&funding_txo) &&
163 !memcmp(OutPoint_get_txid(&mon.first), OutPoint_get_txid(&funding_txo), 32)) {
165 LDKBroadcasterInterface broadcaster = {
166 .broadcast_transaction = broadcast_tx,
168 LDK::CResult_NoneNoneZ res = ChannelMonitor_update_monitor(&mon.second, update, &broadcaster, fee_est, arg->logger);
169 assert(res->result_ok);
175 return ChannelMonitorUpdateStatus_completed();
177 LDKCVec_C3Tuple_OutPointCVec_MonitorEventZPublicKeyZZ monitors_pending_monitor_events(const void *this_arg) {
178 NodeMonitors* arg = (NodeMonitors*) this_arg;
179 std::unique_lock<std::mutex> l(arg->mut);
181 if (arg->mons.size() == 0) {
182 return LDKCVec_C3Tuple_OutPointCVec_MonitorEventZPublicKeyZZ {
187 // We only ever actually have one channel per node, plus concatenating two
188 // Rust Vecs to each other from C++ will require a bit of effort.
189 assert(arg->mons.size() == 1);
190 LDK::CVec_MonitorEventZ events = ChannelMonitor_get_and_clear_pending_monitor_events(&arg->mons[0].second);
191 LDK::C2Tuple_OutPointScriptZ funding_info = ChannelMonitor_get_funding_txo(&arg->mons[0].second);
192 LDK::OutPoint outpoint = std::move(funding_info->a);
193 LDKPublicKey counterparty_node_id = ChannelMonitor_get_counterparty_node_id(&arg->mons[0].second);
194 LDK::C3Tuple_OutPointCVec_MonitorEventZPublicKeyZ tuple = C3Tuple_OutPointCVec_MonitorEventZPublicKeyZ_new(std::move(outpoint), std::move(events), std::move(counterparty_node_id));
195 auto vec = LDKCVec_C3Tuple_OutPointCVec_MonitorEventZPublicKeyZZ {
196 .data = (LDKC3Tuple_OutPointCVec_MonitorEventZPublicKeyZ*)malloc(sizeof(LDKC3Tuple_OutPointCVec_MonitorEventZPublicKeyZ)),
199 vec.data[0] = std::move(tuple);
205 std::vector<LDK::Event> events;
207 void handle_event(const void *this_arg, LDKEvent event) {
208 EventQueue* arg = (EventQueue*) this_arg;
209 arg->events.push_back(std::move(event));
213 class PeersConnection {
218 PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
219 node1_handler = init_socket_handling(&net1);
220 node2_handler = init_socket_handling(&net2);
222 struct sockaddr_in listen_addr;
223 listen_addr.sin_family = AF_INET;
224 listen_addr.sin_addr.s_addr = htonl((127 << 8*3) | 1);
225 listen_addr.sin_port = htons(10042);
226 assert(!socket_bind(node2_handler, (sockaddr*)&listen_addr, sizeof(listen_addr)));
228 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
230 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
232 // Wait for the initial handshakes to complete...
233 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
234 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
235 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
236 std::this_thread::yield();
238 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
240 // Connect twice, which should auto-disconnect, and is a good test of our disconnect pipeline
241 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
242 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
244 // Then disconnect the "main" connection, while another connection is being made.
245 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2));
246 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
248 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting new connection handshake..." << std::endl;
250 // Wait for the new connection handshake...
251 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
252 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
253 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
254 std::this_thread::yield();
256 std::cout << __FILE__ << ":" << __LINE__ << " - " << "New connection handshake complete!" << std::endl;
258 // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
259 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting peer disconnection..." << std::endl;
261 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2));
262 // Wait for the peers to disconnect...
263 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
264 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
265 if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
266 std::this_thread::yield();
268 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Peers disconnected!" << std::endl;
269 // Note that the above is somewhat race-y, as node 2 may still think its connected.
270 // Thus, make sure any connections are disconnected on its end as well.
271 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1));
273 // Finally make an actual connection and keep it this time
274 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
276 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
278 // Wait for the initial handshakes to complete...
279 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
280 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
281 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
282 std::this_thread::yield();
284 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
287 interrupt_socket_handling(node1_handler);
288 interrupt_socket_handling(node2_handler);
294 uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
295 return write((int)((long)this_arg), data.data, data.datalen);
297 void sock_disconnect_socket(void *this_arg) {
298 close((int)((long)this_arg));
300 bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) {
301 return this_arg == other_arg->this_arg;
303 uint64_t sock_hash(const void *this_arg) {
304 return (uint64_t)this_arg;
306 void sock_read_data_thread(int rdfd, LDKSocketDescriptor *peer_descriptor, LDKPeerManager *pm) {
307 unsigned char buf[1024];
311 while ((readlen = read(rdfd, buf, 1024)) > 0) {
312 data.datalen = readlen;
313 LDK::CResult_boolPeerHandleErrorZ res = PeerManager_read_event(&*pm, peer_descriptor, data);
314 if (!res->result_ok) {
315 peer_descriptor->disconnect_socket(peer_descriptor->this_arg);
318 PeerManager_process_events(pm);
320 PeerManager_socket_disconnected(&*pm, peer_descriptor);
323 class PeersConnection {
324 int pipefds_1_to_2[2];
325 int pipefds_2_to_1[2];
327 LDKSocketDescriptor sock1, sock2;
330 PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
331 assert(!pipe(pipefds_1_to_2));
332 assert(!pipe(pipefds_2_to_1));
334 sock1 = LDKSocketDescriptor {
335 .this_arg = (void*)(long)pipefds_1_to_2[1],
336 .send_data = sock_send_data,
337 .disconnect_socket = sock_disconnect_socket,
344 sock2 = LDKSocketDescriptor {
345 .this_arg = (void*)(long)pipefds_2_to_1[1],
346 .send_data = sock_send_data,
347 .disconnect_socket = sock_disconnect_socket,
354 t1 = std::thread(&sock_read_data_thread, pipefds_2_to_1[0], &sock1, &net1);
355 t2 = std::thread(&sock_read_data_thread, pipefds_1_to_2[0], &sock2, &net2);
357 // Note that we have to bind the result to a C++ class to make sure it gets free'd
358 LDK::CResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(&net1, ChannelManager_get_our_node_id(&cm2), sock1, COption_NetAddressZ_none());
359 assert(con_res->result_ok);
360 LDK::CResult_NonePeerHandleErrorZ con_res2 = PeerManager_new_inbound_connection(&net2, sock2, COption_NetAddressZ_none());
361 assert(con_res2->result_ok);
363 auto writelen = write(pipefds_1_to_2[1], con_res->contents.result->data, con_res->contents.result->datalen);
364 assert(writelen > 0 && uint64_t(writelen) == con_res->contents.result->datalen);
366 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
368 // Wait for the initial handshakes to complete...
369 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
370 LDK::CVec_C2Tuple_PublicKeyCOption_NetAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
371 if (peers_1->datalen == 1 && peers_2->datalen ==1) { break; }
372 std::this_thread::yield();
374 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
378 close(pipefds_1_to_2[0]);
379 close(pipefds_2_to_1[0]);
380 close(pipefds_1_to_2[1]);
381 close(pipefds_2_to_1[1]);
388 struct CustomOnionMsgQueue {
390 std::vector<LDK::CustomOnionMessageContents> msgs;
393 uint64_t custom_onion_msg_type_id(const void *this_arg) {
396 LDKCVec_u8Z custom_onion_msg_bytes(const void *this_arg) {
397 uint8_t *bytes = (uint8_t *) malloc(1024);
398 memset(bytes, 43, 1024);
400 .data = bytes, .datalen = 1024
404 void handle_custom_onion_message(const void* this_arg, struct LDKCustomOnionMessageContents msg) {
405 CustomOnionMsgQueue* arg = (CustomOnionMsgQueue*) this_arg;
406 std::unique_lock<std::mutex> lck(arg->mtx);
407 arg->msgs.push_back(std::move(msg));
410 LDKCustomOnionMessageContents build_custom_onion_message() {
411 return LDKCustomOnionMessageContents {
413 .tlv_type = custom_onion_msg_type_id,
414 .write = custom_onion_msg_bytes,
419 LDKCResult_COption_CustomOnionMessageContentsZDecodeErrorZ read_custom_onion_message(const void* this_arg, uint64_t type, LDKu8slice buf) {
420 assert(type == 8888);
421 assert(buf.datalen == 1024);
423 memset(cmp, 43, 1024);
424 assert(!memcmp(cmp, buf.data, 1024));
425 return CResult_COption_CustomOnionMessageContentsZDecodeErrorZ_ok(COption_CustomOnionMessageContentsZ_some(build_custom_onion_message()));
429 struct CustomMsgQueue {
430 std::vector<LDK::Type> msgs;
433 uint16_t custom_msg_type_id(const void *this_arg) {
436 LDKCVec_u8Z custom_msg_bytes(const void *this_arg) {
437 uint8_t *bytes = (uint8_t *) malloc(1024);
438 memset(bytes, 42, 1024);
440 .data = bytes, .datalen = 1024
443 LDKStr custom_msg_debug(const void *this_arg) {
445 .chars = (const unsigned char*) "Custom Message", .len = 14, .chars_is_owned = false
449 LDKCResult_COption_TypeZDecodeErrorZ read_custom_message(const void* this_arg, uint16_t type_id, LDKu8slice buf) {
450 assert(type_id == 8888);
451 assert(buf.datalen == 1024);
453 memset(cmp, 42, 1024);
454 assert(!memcmp(cmp, buf.data, 1024));
455 return CResult_COption_TypeZDecodeErrorZ_ok(COption_TypeZ_some(LDKType {
457 .type_id = custom_msg_type_id,
458 .debug_str = custom_msg_debug,
463 LDKCResult_NoneLightningErrorZ handle_custom_message(const void* this_arg, struct LDKType msg, struct LDKPublicKey _sender_node_id) {
464 CustomMsgQueue* arg = (CustomMsgQueue*) this_arg;
465 arg->msgs.push_back(std::move(msg));
466 return CResult_NoneLightningErrorZ_ok();
468 LDKCVec_C2Tuple_PublicKeyTypeZZ never_send_custom_msgs(const void* this_arg) {
469 return LDKCVec_C2Tuple_PublicKeyTypeZZ {
470 .data = NULL, .datalen = 0
474 LDKCVec_C2Tuple_PublicKeyTypeZZ create_custom_msg(const void* this_arg) {
475 const LDKPublicKey *counterparty_node_id = (const LDKPublicKey *)this_arg;
476 LDKCVec_C2Tuple_PublicKeyTypeZZ ret = {
477 .data = ((LDKC2Tuple_PublicKeyTypeZ*)malloc(sizeof(LDKC2Tuple_PublicKeyTypeZ))),
480 ret.data[0].a = *counterparty_node_id;
481 ret.data[0].b = LDKType {
483 .type_id = custom_msg_type_id,
484 .debug_str = custom_msg_debug,
485 .write = custom_msg_bytes,
491 uint64_t get_chan_score(const void *this_arg, uint64_t scid, const LDKNodeId *src, const LDKNodeId *dst, LDKChannelUsage usage_in) {
492 LDK::ChannelUsage usage(std::move(usage_in));
496 struct LDKCResult_RouteLightningErrorZ custom_find_route(const void *this_arg, struct LDKPublicKey payer, const struct LDKRouteParameters *NONNULL_PTR route_params, struct LDKCVec_ChannelDetailsZ *first_hops, const struct LDKInFlightHtlcs *in_flights, LDKThirtyTwoBytes payment_id, LDKThirtyTwoBytes payment_hash) {
497 const LDK::DefaultRouter *router = (LDK::DefaultRouter *)this_arg;
498 assert(first_hops->datalen == 1);
499 assert(ChannelDetails_get_is_usable(&first_hops->data[0]));
500 const LDK::Router router_impl = DefaultRouter_as_Router(&*router);
501 return router_impl->find_route(router_impl->this_arg, payer, route_params, first_hops, in_flights);
505 uint8_t channel_open_header[80];
506 uint8_t header_1[80];
507 uint8_t header_2[80];
508 memcpy(channel_open_header, channel_open_block, 80);
509 memcpy(header_1, block_1, 80);
510 memcpy(header_2, block_2, 80);
512 LDKPublicKey null_pk;
513 memset(&null_pk, 0, sizeof(null_pk));
515 LDKThirtyTwoBytes random_bytes;
516 LDKThirtyTwoBytes chain_tip;
517 memset(&chain_tip, 0, sizeof(chain_tip)); // channel_open_header's prev_blockhash is all-0s
519 LDKNetwork network = LDKNetwork_Testnet;
521 // Trait implementations:
522 LDKBroadcasterInterface broadcast {
524 .broadcast_transaction = broadcast_tx,
528 // Instantiate classes for the nodes that don't get reloaded on a ser-des reload
530 .this_arg = (void*)1,
536 mons1.logger = &logger1;
539 .watch_channel = add_channel_monitor,
540 .update_channel = update_channel_monitor,
541 .release_pending_monitor_events = monitors_pending_monitor_events,
545 LDK::NetworkGraph net_graph1 = NetworkGraph_new(network, logger1);
546 LDK::P2PGossipSync graph_msg_handler1 = P2PGossipSync_new(&net_graph1, COption_UtxoLookupZ_none(), logger1);
549 .this_arg = (void*)2,
555 mons2.logger = &logger2;
558 .watch_channel = add_channel_monitor,
559 .update_channel = update_channel_monitor,
560 .release_pending_monitor_events = monitors_pending_monitor_events,
564 LDKRouter panic_router = {
566 .find_route = NULL, // Segfault if we ever try to find a route
567 .find_route_with_id = NULL, // Segfault if we ever try to find a route
571 LDK::NetworkGraph net_graph2 = NetworkGraph_new(network, logger2);
572 LDK::P2PGossipSync graph_msg_handler2 = P2PGossipSync_new(&net_graph2, COption_UtxoLookupZ_none(), logger2);
574 LDK::CVec_u8Z cm1_ser = LDKCVec_u8Z {}; // ChannelManager 1 serialization at the end of the ser-des scope
575 LDK::CVec_u8Z cm2_ser = LDKCVec_u8Z {}; // ChannelManager 2 serialization at the end of the ser-des scope
577 { // Scope for the ser-des reload
578 // Instantiate classes for node 1:
579 uint8_t node_seed[32];
580 memset(&node_seed, 0, 32);
581 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 0, 0);
582 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
583 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
584 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
586 LDK::ChannelManager cm1 = ChannelManager_new(fee_est, mon1, broadcast, panic_router, logger1, KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), KeysManager_as_SignerProvider(&keys1), UserConfig_default(), ChainParameters_new(network, BestBlock_new(chain_tip, 0)));
588 LDK::IgnoringMessageHandler ignoring_handler1 = IgnoringMessageHandler_new();
589 LDK::CustomMessageHandler custom_msg_handler1 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler1);
590 LDK::CustomOnionMessageHandler custom_onion_msg_handler1 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler1);
592 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, std::move(custom_onion_msg_handler1));
594 LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
595 assert(channels->datalen == 0);
597 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler1), OnionMessenger_as_OnionMessageHandler(&om1));
599 random_bytes = entropy_source1.get_secure_random_bytes();
600 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(custom_msg_handler1), std::move(node_signer1));
602 // Demo getting a channel key and check that its returning real pubkeys:
603 LDKSixteenBytes user_id_1 { .data = {45, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0} };
604 LDKThirtyTwoBytes chan_signer_id1 = signer_provider1.generate_channel_keys_id(false, 42, U128_new(user_id_1));
605 LDK::WriteableEcdsaChannelSigner chan_signer1 = signer_provider1.derive_channel_signer(42, chan_signer_id1);
606 chan_signer1->EcdsaChannelSigner.ChannelSigner.set_pubkeys(&chan_signer1->EcdsaChannelSigner.ChannelSigner); // Make sure pubkeys is defined
607 LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->EcdsaChannelSigner.ChannelSigner.pubkeys);
608 assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
610 // Instantiate classes for node 2:
611 memset(&node_seed, 1, 32);
612 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 0, 0);
613 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
614 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
615 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
617 LDK::ChannelHandshakeConfig handshake_config2 = ChannelHandshakeConfig_default();
618 ChannelHandshakeConfig_set_minimum_depth(&handshake_config2, 2);
619 LDK::UserConfig config2 = UserConfig_default();
620 UserConfig_set_channel_handshake_config(&config2, std::move(handshake_config2));
622 LDK::ChannelManager cm2 = ChannelManager_new(fee_est, mon2, broadcast, panic_router, logger2, KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), KeysManager_as_SignerProvider(&keys2), std::move(config2), ChainParameters_new(network, BestBlock_new(chain_tip, 0)));
624 LDK::IgnoringMessageHandler ignoring_handler2 = IgnoringMessageHandler_new();
625 LDK::CustomMessageHandler custom_msg_handler2 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler2);
626 LDK::CustomOnionMessageHandler custom_onion_msg_handler2 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler2);
628 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, std::move(custom_onion_msg_handler2));
630 LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
631 assert(channels2->datalen == 0);
633 LDK::RoutingMessageHandler net_msgs2 = P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2);
634 LDK::CResult_ChannelAnnouncementDecodeErrorZ chan_ann = ChannelAnnouncement_read(LDKu8slice { .data = valid_node_announcement, .datalen = sizeof(valid_node_announcement) });
635 assert(chan_ann->result_ok);
636 LDK::CResult_boolLightningErrorZ ann_res = net_msgs2->handle_channel_announcement(net_msgs2->this_arg, chan_ann->contents.result);
637 assert(ann_res->result_ok);
639 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), std::move(net_msgs2), OnionMessenger_as_OnionMessageHandler(&om1));
641 random_bytes = entropy_source2.get_secure_random_bytes();
642 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(custom_msg_handler2), std::move(node_signer2));
644 // Open a connection!
645 PeersConnection conn(cm1, cm2, net1, net2);
647 // Note that we have to bind the result to a C++ class to make sure it gets free'd
648 LDK::CResult__u832APIErrorZ res = ChannelManager_create_channel(&cm1, ChannelManager_get_our_node_id(&cm2), 40000, 1000, U128_new(user_id_1), UserConfig_default());
649 assert(res->result_ok);
650 PeerManager_process_events(&net1);
652 LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
653 assert(new_channels->datalen == 1);
654 LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
655 LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
656 assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
658 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting first channel..." << std::endl;
660 LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
661 if (new_channels_2->datalen == 1) {
662 // Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
663 LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
664 const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
665 assert(init_feats->inner != NULL);
668 std::this_thread::yield();
670 std::cout << __FILE__ << ":" << __LINE__ << " - " << "First channel listed!" << std::endl;
672 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
673 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting FundingGenerationReady event..." << std::endl;
676 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
677 ev1.process_pending_events(handler);
678 if (queue.events.size() == 1) {
679 assert(queue.events[0]->tag == LDKEvent_FundingGenerationReady);
680 LDKSixteenBytes event_id = U128_le_bytes(queue.events[0]->funding_generation_ready.user_channel_id);
681 assert(!memcmp(&event_id, &user_id_1, 16));
682 assert(queue.events[0]->funding_generation_ready.channel_value_satoshis == 40000);
683 assert(queue.events[0]->funding_generation_ready.output_script.datalen == 34);
685 assert(!memcmp(queue.events[0]->funding_generation_ready.output_script.data, channel_open_block + 58 + 81, 34));
686 LDKTransaction funding_transaction { .data = const_cast<uint8_t*>(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false };
688 LDK::CResult_NoneAPIErrorZ fund_res = ChannelManager_funding_transaction_generated(&cm1, &queue.events[0]->funding_generation_ready.temporary_channel_id.data, queue.events[0]->funding_generation_ready.counterparty_node_id, funding_transaction);
689 assert(fund_res->result_ok);
692 std::this_thread::yield();
694 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received FundingGenerationReady event!" << std::endl;
696 // We observe when the funding signed messages have been exchanged by
697 // waiting for two monitors to be registered.
698 assert(num_txs_broadcasted == 0);
699 PeerManager_process_events(&net1);
700 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting transaction broadcast..." << std::endl;
701 while (num_txs_broadcasted != 1) {
702 std::this_thread::yield();
704 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Transaction was broadcast!" << std::endl;
706 // Note that the channel ID is the same as the channel txid reversed as the output index is 0
707 uint8_t expected_chan_id[32];
708 for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
710 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
713 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
714 ev1.process_pending_events(handler);
715 if (queue.events.size() == 1) {
716 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
717 assert(!memcmp(queue.events[0]->channel_pending.channel_id.data, expected_chan_id, 32));
720 std::this_thread::yield();
722 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
724 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
725 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
728 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
729 ev2.process_pending_events(handler);
730 if (queue.events.size() == 1) {
731 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
732 assert(!memcmp(queue.events[0]->channel_pending.channel_id.data, expected_chan_id, 32));
735 std::this_thread::yield();
737 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
739 LDK::Listen listener1 = ChannelManager_as_Listen(&cm1);
740 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
742 LDK::Listen listener2 = ChannelManager_as_Listen(&cm2);
743 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
745 LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
746 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
747 mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
749 txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
750 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
751 mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
753 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
754 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
755 mons1.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
756 mons2.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
758 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
759 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
760 mons1.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
761 mons2.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
763 PeerManager_process_events(&net1);
764 PeerManager_process_events(&net2);
766 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
769 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
770 ev2.process_pending_events(handler);
771 if (queue.events.size() == 1) {
772 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
773 assert(!memcmp(queue.events[0]->channel_ready.channel_id.data, expected_chan_id, 32));
776 std::this_thread::yield();
778 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
780 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
783 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
784 ev1.process_pending_events(handler);
785 if (queue.events.size() == 1) {
786 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
787 assert(!memcmp(queue.events[0]->channel_ready.channel_id.data, expected_chan_id, 32));
790 std::this_thread::yield();
792 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
794 // Now send funds from 1 to 2!
795 uint64_t channel_scid;
796 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
798 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
799 if (outbound_channels->datalen == 1) {
800 const LDKChannelDetails *channel = &outbound_channels->data[0];
801 LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
803 assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
805 ChannelCounterparty_get_node_id(&counterparty).compressed_form,
806 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
807 assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
808 // We opened the channel with 1000 push_msat:
809 assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
810 40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
811 int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
812 if (inbound_capacity < 0) inbound_capacity = 0;
813 assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
814 assert(ChannelDetails_get_is_usable(channel));
815 LDK::COption_u64Z scid_opt = ChannelDetails_get_short_channel_id(channel);
816 assert(scid_opt->some);
817 channel_scid = scid_opt->some;
820 std::this_thread::yield();
822 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
824 LDKCOption_u64Z min_value = {
825 .tag = LDKCOption_u64Z_Some,
828 LDK::CResult_InvoiceSignOrCreationErrorZ invoice = create_invoice_from_channelmanager(&cm2,
829 KeysManager_as_NodeSigner(&keys2), logger2,
830 LDKCurrency_Bitcoin, min_value,
832 .chars = (const uint8_t *)"Invoice Description",
833 .len = strlen("Invoice Description"),
834 .chars_is_owned = false
835 }, 3600, COption_u16Z_none());
836 assert(invoice->result_ok);
837 LDKThirtyTwoBytes payment_hash;
838 memcpy(payment_hash.data, Invoice_payment_hash(invoice->contents.result), 32);
841 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
842 LDK::Score chan_scorer = LDKScore {
843 .this_arg = NULL, .channel_penalty_msat = get_chan_score, .free = NULL
845 LDK::RouteParameters route_params = RouteParameters_new(PaymentParameters_new(
846 ChannelManager_get_our_node_id(&cm2), LDKInvoiceFeatures {
847 .inner = NULL, .is_owned = false
848 }, Hints_clear(Invoice_route_hints(invoice->contents.result)), COption_u64Z_none(),
849 0xffffffff, 1, 2, LDKCVec_u64Z { .data = NULL, .datalen = 0 },
850 Invoice_min_final_cltv_expiry_delta(invoice->contents.result)),
852 random_bytes = entropy_source1.get_secure_random_bytes();
854 LDK::CResult_RouteLightningErrorZ route = find_route(ChannelManager_get_our_node_id(&cm1), &route_params, &net_graph2, &outbound_channels, logger1, &chan_scorer, &random_bytes.data);
856 assert(route->result_ok);
857 LDK::CVec_PathZ paths = Route_get_paths(route->contents.result);
858 assert(paths->datalen == 1);
859 LDK::CVec_RouteHopZ hops = Path_get_hops(&paths->data[0]);
860 assert(hops->datalen == 1);
861 assert(!memcmp(RouteHop_get_pubkey(&hops->data[0]).compressed_form,
862 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
863 assert(RouteHop_get_short_channel_id(&hops->data[0]) == channel_scid);
864 LDKThirtyTwoBytes payment_secret;
865 memcpy(payment_secret.data, Invoice_payment_secret(invoice->contents.result), 32);
866 LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment_with_route(&cm1,
867 route->contents.result, payment_hash, RecipientOnionFields_secret_only(payment_secret), payment_hash);
868 assert(send_res->result_ok);
872 PeerManager_process_events(&net1);
873 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 4 updated monitors..." << std::endl;
874 while (mons_updated != 4) {
875 std::this_thread::yield();
877 std::cout << __FILE__ << ":" << __LINE__ << " - " << "4 monitors updated!" << std::endl;
879 // Check that we received the payment!
880 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
883 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
884 ev2.process_pending_events(handler);
885 if (queue.events.size() == 1) {
886 assert(queue.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
889 std::this_thread::yield();
891 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
892 ChannelManager_process_pending_htlc_forwards(&cm2);
893 PeerManager_process_events(&net2);
896 LDKThirtyTwoBytes payment_preimage;
899 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
900 ev2.process_pending_events(handler);
901 assert(queue.events.size() == 1);
902 assert(queue.events[0]->tag == LDKEvent_PaymentClaimable);
903 assert(!memcmp(queue.events[0]->payment_claimable.payment_hash.data, payment_hash.data, 32));
904 assert(queue.events[0]->payment_claimable.purpose.tag == LDKPaymentPurpose_InvoicePayment);
905 assert(!memcmp(queue.events[0]->payment_claimable.purpose.invoice_payment.payment_secret.data,
906 Invoice_payment_secret(invoice->contents.result), 32));
907 assert(queue.events[0]->payment_claimable.amount_msat == 5000);
908 memcpy(payment_preimage.data, queue.events[0]->payment_claimable.purpose.invoice_payment.payment_preimage.data, 32);
909 ChannelManager_claim_funds(&cm2, payment_preimage);
911 queue.events.clear();
912 ev2.process_pending_events(handler);
913 assert(queue.events.size() == 1);
914 assert(queue.events[0]->tag == LDKEvent_PaymentClaimed);
915 assert(!memcmp(queue.events[0]->payment_claimed.payment_hash.data, payment_hash.data, 32));
916 assert(queue.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_InvoicePayment);
918 PeerManager_process_events(&net2);
919 // Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
920 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 5 updated monitors..." << std::endl;
921 while (mons_updated != 5) {
922 std::this_thread::yield();
924 std::cout << __FILE__ << ":" << __LINE__ << " - " << "5 monitors updated!" << std::endl;
927 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
928 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
929 while (queue.events.size() < 2) {
930 ev1.process_pending_events(handler);
931 std::this_thread::yield();
933 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
934 assert(queue.events.size() == 2);
935 assert(queue.events[0]->tag == LDKEvent_PaymentSent);
936 assert(!memcmp(queue.events[0]->payment_sent.payment_preimage.data, payment_preimage.data, 32));
937 assert(queue.events[1]->tag == LDKEvent_PaymentPathSuccessful);
938 assert(!memcmp(queue.events[1]->payment_path_successful.payment_hash.data, payment_hash.data, 32));
943 cm1_ser = ChannelManager_write(&cm1);
944 cm2_ser = ChannelManager_write(&cm2);
947 LDK::CVec_ChannelMonitorZ mons_list1 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
948 assert(mons1.mons.size() == 1);
949 mons_list1->data[0] = *& std::get<1>(mons1.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
950 mons_list1->data[0].is_owned = false; // XXX: God this sucks
951 uint8_t node_seed[32];
952 memset(&node_seed, 0, 32);
953 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 1, 0);
954 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
955 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
956 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
958 LDK::ProbabilisticScorer scorer1 = ProbabilisticScorer_new(ProbabilisticScoringParameters_default(), &net_graph1, logger1);
959 LDK::Score scorer_trait1 = ProbabilisticScorer_as_Score(&scorer1);
960 LDK::MultiThreadedLockableScore scorer_mtx1 = MultiThreadedLockableScore_new(std::move(scorer_trait1));
961 LDK::LockableScore scorer_mtx_trait1 = MultiThreadedLockableScore_as_LockableScore(&scorer_mtx1);
962 const LDK::DefaultRouter default_router_1 = DefaultRouter_new(&net_graph1, logger1, entropy_source1.get_secure_random_bytes(), std::move(scorer_mtx_trait1));
963 LDKRouter router1 = {
964 .this_arg = (void*)&default_router_1,
965 .find_route = NULL, // LDK currently doesn't use this, its just a default-impl
966 .find_route_with_id = custom_find_route,
970 LDK::ChannelManagerReadArgs cm1_args = ChannelManagerReadArgs_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), KeysManager_as_SignerProvider(&keys1), fee_est, mon1, broadcast, router1, logger1, UserConfig_default(), std::move(mons_list1));
971 LDK::CResult_C2Tuple_BlockHashChannelManagerZDecodeErrorZ cm1_read =
972 C2Tuple_BlockHashChannelManagerZ_read(LDKu8slice { .data = cm1_ser->data, .datalen = cm1_ser -> datalen}, std::move(cm1_args));
973 assert(cm1_read->result_ok);
974 LDK::ChannelManager cm1(std::move(cm1_read->contents.result->b));
976 LDKCustomOnionMessageHandler custom_onion_msg_handler1 = {
978 .handle_custom_message = NULL, // We only create custom messages, not handle them
979 .read_custom_message = NULL, // We only create custom messages, not handle them
982 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, custom_onion_msg_handler1);
984 LDK::CVec_ChannelMonitorZ mons_list2 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
985 assert(mons2.mons.size() == 1);
986 mons_list2->data[0] = *& std::get<1>(mons2.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
987 mons_list2->data[0].is_owned = false; // XXX: God this sucks
988 memset(&node_seed, 1, 32);
989 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 1, 0);
990 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
991 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
992 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
994 LDK::ChannelManagerReadArgs cm2_args = ChannelManagerReadArgs_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), KeysManager_as_SignerProvider(&keys2), fee_est, mon2, broadcast, panic_router, logger2, UserConfig_default(), std::move(mons_list2));
995 LDK::CResult_C2Tuple_BlockHashChannelManagerZDecodeErrorZ cm2_read =
996 C2Tuple_BlockHashChannelManagerZ_read(LDKu8slice { .data = cm2_ser->data, .datalen = cm2_ser -> datalen}, std::move(cm2_args));
997 assert(cm2_read->result_ok);
998 LDK::ChannelManager cm2(std::move(cm2_read->contents.result->b));
1000 CustomOnionMsgQueue peer_2_custom_onion_messages;
1001 LDKCustomOnionMessageHandler custom_onion_msg_handler2 = {
1002 .this_arg = &peer_2_custom_onion_messages,
1003 .handle_custom_message = handle_custom_onion_message,
1004 .read_custom_message = read_custom_onion_message,
1007 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, custom_onion_msg_handler2);
1009 // Attempt to close the channel...
1010 uint8_t chan_id[32];
1011 for (int i = 0; i < 32; i++) { chan_id[i] = channel_open_txid[31-i]; }
1012 LDK::CResult_NoneAPIErrorZ close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1013 assert(!close_res->result_ok); // Note that we can't close while disconnected!
1015 // Open a connection!
1016 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler1), OnionMessenger_as_OnionMessageHandler(&om1));
1017 random_bytes = entropy_source1.get_secure_random_bytes();
1019 LDKPublicKey chan_2_node_id = ChannelManager_get_our_node_id(&cm2);
1020 LDKCustomMessageHandler custom_msg_handler1 = {
1021 .this_arg = &chan_2_node_id,
1022 .handle_custom_message = NULL, // We only create custom messages, not handle them
1023 .get_and_clear_pending_msg = create_custom_msg,
1024 .CustomMessageReader = LDKCustomMessageReader {
1026 .read = read_custom_message,
1031 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(custom_msg_handler1), std::move(node_signer1));
1033 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2), OnionMessenger_as_OnionMessageHandler(&om2));
1034 CustomMsgQueue peer_2_custom_messages;
1035 LDKCustomMessageHandler custom_msg_handler2 = {
1036 .this_arg = &peer_2_custom_messages,
1037 .handle_custom_message = handle_custom_message,
1038 .get_and_clear_pending_msg = never_send_custom_msgs,
1039 .CustomMessageReader = LDKCustomMessageReader {
1041 .read = read_custom_message,
1046 random_bytes = entropy_source1.get_secure_random_bytes();
1047 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(custom_msg_handler2), std::move(node_signer2));
1049 PeersConnection conn(cm1, cm2, net1, net2);
1051 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
1053 // Wait for the channels to be considered up once the reestablish messages are processed
1054 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
1055 if (outbound_channels->datalen == 1) {
1058 std::this_thread::yield();
1060 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
1062 // Send another payment, this time via the retires path
1063 LDK::CResult_InvoiceSignOrCreationErrorZ invoice_res2 = create_invoice_from_channelmanager(&cm2,
1064 KeysManager_as_NodeSigner(&keys2), logger1,
1065 LDKCurrency_Bitcoin, COption_u64Z_some(10000),
1067 .chars = (const uint8_t *)"Invoice 2 Description",
1068 .len = strlen("Invoice 2 Description"),
1069 .chars_is_owned = false
1070 }, 3600, COption_u16Z_none());
1071 assert(invoice_res2->result_ok);
1072 const LDKInvoice *invoice2 = invoice_res2->contents.result;
1073 LDK::CResult_PaymentIdPaymentErrorZ invoice_pay_res = pay_invoice(invoice2, Retry_attempts(0), &cm1);
1074 assert(invoice_pay_res->result_ok);
1075 PeerManager_process_events(&net1);
1077 // Check that we received the payment!
1078 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
1081 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1082 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1083 ev2.process_pending_events(handler2);
1084 if (queue2.events.size() == 1) {
1085 assert(queue2.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
1088 std::this_thread::yield();
1090 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
1091 ChannelManager_process_pending_htlc_forwards(&cm2);
1092 PeerManager_process_events(&net2);
1094 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentClaimable/PaymentClaimed event..." << std::endl;
1097 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1098 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1099 ev2.process_pending_events(handler2);
1100 if (queue2.events.size() == 1) {
1101 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimable);
1102 const struct LDKEvent_LDKPaymentClaimable_Body *event_data = &queue2.events[0]->payment_claimable;
1103 assert(!memcmp(event_data->payment_hash.data, Invoice_payment_hash(invoice2), 32));
1104 assert(event_data->purpose.tag == LDKPaymentPurpose_InvoicePayment);
1105 assert(!memcmp(event_data->purpose.invoice_payment.payment_secret.data,
1106 Invoice_payment_secret(invoice2), 32));
1107 assert(event_data->amount_msat == 10000);
1108 ChannelManager_claim_funds(&cm2, event_data->purpose.invoice_payment.payment_preimage);
1110 queue2.events.clear();
1111 ev2.process_pending_events(handler2);
1112 assert(queue2.events.size() == 1);
1113 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimed);
1114 assert(!memcmp(queue2.events[0]->payment_claimed.payment_hash.data, Invoice_payment_hash(invoice2), 32));
1115 assert(queue2.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_InvoicePayment);
1119 std::this_thread::yield();
1121 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentClaimable/PaymentClaimed event!" << std::endl;
1124 LDKEventHandler handler1 = { .this_arg = &queue1, .handle_event = handle_event, .free = NULL };
1125 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
1126 while (queue1.events.size() < 2) {
1127 PeerManager_process_events(&net2);
1128 PeerManager_process_events(&net1);
1130 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
1131 ev1.process_pending_events(handler1);
1132 std::this_thread::yield();
1134 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
1135 assert(queue1.events.size() == 2);
1136 assert(queue1.events[0]->tag == LDKEvent_PaymentSent);
1137 assert(queue1.events[1]->tag == LDKEvent_PaymentPathSuccessful);
1139 // Actually close the channel
1140 num_txs_broadcasted = 0;
1141 close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1142 assert(close_res->result_ok);
1143 PeerManager_process_events(&net1);
1144 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 2 transaction broadcasts..." << std::endl;
1145 while (num_txs_broadcasted != 2) {
1146 std::this_thread::yield();
1148 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Broadcast 2 transactions!" << std::endl;
1149 LDK::CVec_ChannelDetailsZ chans_after_close1 = ChannelManager_list_channels(&cm1);
1150 assert(chans_after_close1->datalen == 0);
1151 LDK::CVec_ChannelDetailsZ chans_after_close2 = ChannelManager_list_channels(&cm2);
1152 assert(chans_after_close2->datalen == 0);
1154 assert(OnionMessenger_send_onion_message(&om1,
1155 LDKCVec_PublicKeyZ { .data = NULL, .datalen = 0, },
1156 Destination_node(ChannelManager_get_our_node_id(&cm2)),
1157 LDKOnionMessageContents {
1158 .tag = LDKOnionMessageContents_Custom,
1159 .custom = build_custom_onion_message()
1160 }, LDKBlindedPath { .inner = NULL, .is_owned = true })
1162 PeerManager_process_events(&net1);
1163 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting onion message..." << std::endl;
1165 std::this_thread::yield();
1166 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1167 if (peer_2_custom_onion_messages.msgs.size() != 0) break;
1169 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received onion message!" << std::endl;
1173 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1174 assert(peer_2_custom_onion_messages.msgs.size() == 1);
1175 assert(peer_2_custom_onion_messages.msgs[0].tlv_type() == 8888);
1176 assert(peer_2_custom_messages.msgs.size() != 0);
1178 // Few extra random tests:
1180 memset(&sk, 42, 32);
1181 LDKThirtyTwoBytes kdiv_params;
1182 memset(&kdiv_params, 43, 32);
1183 LDK::InMemorySigner signer = InMemorySigner_new(sk, sk, sk, sk, sk, random_bytes, 42, kdiv_params, kdiv_params);