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, LDKRecord record_arg) {
101 LDK::Record record(std::move(record_arg));
102 LDK::Str mod = Record_get_module_path(&record);
103 LDK::Str str = Record_get_args(&record);
104 printf("%p - %.*s:%d - %.*s\n", this_arg, (int)mod->len, mod->chars, Record_get_line(&record), (int)str->len, str->chars);
107 uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) {
108 if (target == LDKConfirmationTarget_AnchorChannelFee || target == LDKConfirmationTarget_MinAllowedAnchorChannelRemoteFee) {
113 // Note that we don't call _free() on target, but that's OK, its unitary
115 // We use the same fee estimator globally:
116 const LDKFeeEstimator fee_est {
118 .get_est_sat_per_1000_weight = get_fee,
122 static std::atomic_int num_txs_broadcasted(0);
123 void broadcast_txn(const void *this_arg, LDKCVec_TransactionZ txn) {
124 num_txs_broadcasted += 1;
125 CVec_TransactionZ_free(txn);
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 LDKCResult_ChannelMonitorUpdateStatusNoneZ 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 CResult_ChannelMonitorUpdateStatusNoneZ_ok(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_transactions = broadcast_txn,
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_C4Tuple_OutPointChannelIdCVec_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_C4Tuple_OutPointChannelIdCVec_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_OutPointCVec_u8ZZ 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 LDKThirtyTwoBytes channel_id;
195 memset(&channel_id, 0, sizeof(channel_id));
196 LDK::ChannelId chan_id = ChannelId_new(channel_id);
197 LDK::C4Tuple_OutPointChannelIdCVec_MonitorEventZPublicKeyZ tuple = C4Tuple_OutPointChannelIdCVec_MonitorEventZPublicKeyZ_new(std::move(outpoint), std::move(chan_id), std::move(events), std::move(counterparty_node_id));
198 auto vec = LDKCVec_C4Tuple_OutPointChannelIdCVec_MonitorEventZPublicKeyZZ {
199 .data = (LDKC4Tuple_OutPointChannelIdCVec_MonitorEventZPublicKeyZ*)malloc(sizeof(LDKC4Tuple_OutPointChannelIdCVec_MonitorEventZPublicKeyZ)),
202 vec.data[0] = std::move(tuple);
208 std::vector<LDK::Event> events;
210 void handle_event(const void *this_arg, LDKEvent event) {
211 EventQueue* arg = (EventQueue*) this_arg;
212 arg->events.push_back(std::move(event));
216 class PeersConnection {
221 PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
222 node1_handler = init_socket_handling(&net1);
223 node2_handler = init_socket_handling(&net2);
225 struct sockaddr_in listen_addr;
226 listen_addr.sin_family = AF_INET;
227 listen_addr.sin_addr.s_addr = htonl((127 << 8*3) | 1);
228 listen_addr.sin_port = htons(10042);
229 assert(!socket_bind(node2_handler, (sockaddr*)&listen_addr, sizeof(listen_addr)));
231 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
233 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
235 // Wait for the initial handshakes to complete...
236 LDK::CVec_PeerDetailsZ peers_1 = PeerManager_list_peers(&net1);
237 LDK::CVec_PeerDetailsZ peers_2 = PeerManager_list_peers(&net2);
238 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
239 std::this_thread::yield();
241 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
243 // Connect twice, which should auto-disconnect, and is a good test of our disconnect pipeline
244 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
245 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
247 // Then disconnect the "main" connection, while another connection is being made.
248 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2));
249 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1));
250 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
252 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting new connection handshake..." << std::endl;
254 // Wait for the new connection handshake...
255 LDK::CVec_PeerDetailsZ peers_1 = PeerManager_list_peers(&net1);
256 LDK::CVec_PeerDetailsZ peers_2 = PeerManager_list_peers(&net2);
257 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
258 std::this_thread::yield();
260 std::cout << __FILE__ << ":" << __LINE__ << " - " << "New connection handshake complete!" << std::endl;
262 // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
263 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting peer disconnection..." << std::endl;
265 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2));
266 // Wait for the peers to disconnect...
267 LDK::CVec_PeerDetailsZ peers_1 = PeerManager_list_peers(&net1);
268 LDK::CVec_PeerDetailsZ peers_2 = PeerManager_list_peers(&net2);
269 if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
270 std::this_thread::yield();
272 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Peers disconnected!" << std::endl;
273 // Note that the above is somewhat race-y, as node 2 may still think its connected.
274 // Thus, make sure any connections are disconnected on its end as well.
275 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1));
277 // Finally make an actual connection and keep it this time
278 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
280 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
282 // Wait for the initial handshakes to complete...
283 LDK::CVec_PeerDetailsZ peers_1 = PeerManager_list_peers(&net1);
284 LDK::CVec_PeerDetailsZ peers_2 = PeerManager_list_peers(&net2);
285 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
286 std::this_thread::yield();
288 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
291 interrupt_socket_handling(node1_handler);
292 interrupt_socket_handling(node2_handler);
298 uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
299 return write((int)((long)this_arg), data.data, data.datalen);
301 void sock_disconnect_socket(void *this_arg) {
302 close((int)((long)this_arg));
304 bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) {
305 return this_arg == other_arg->this_arg;
307 uint64_t sock_hash(const void *this_arg) {
308 return (uint64_t)this_arg;
310 void sock_read_data_thread(int rdfd, LDKSocketDescriptor *peer_descriptor, LDKPeerManager *pm) {
311 unsigned char buf[1024];
315 while ((readlen = read(rdfd, buf, 1024)) > 0) {
316 data.datalen = readlen;
317 LDK::CResult_boolPeerHandleErrorZ res = PeerManager_read_event(&*pm, peer_descriptor, data);
318 if (!res->result_ok) {
319 peer_descriptor->disconnect_socket(peer_descriptor->this_arg);
322 PeerManager_process_events(pm);
324 PeerManager_socket_disconnected(&*pm, peer_descriptor);
327 class PeersConnection {
328 int pipefds_1_to_2[2];
329 int pipefds_2_to_1[2];
331 LDKSocketDescriptor sock1, sock2;
334 PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
335 assert(!pipe(pipefds_1_to_2));
336 assert(!pipe(pipefds_2_to_1));
338 sock1 = LDKSocketDescriptor {
339 .this_arg = (void*)(long)pipefds_1_to_2[1],
340 .send_data = sock_send_data,
341 .disconnect_socket = sock_disconnect_socket,
348 sock2 = LDKSocketDescriptor {
349 .this_arg = (void*)(long)pipefds_2_to_1[1],
350 .send_data = sock_send_data,
351 .disconnect_socket = sock_disconnect_socket,
358 t1 = std::thread(&sock_read_data_thread, pipefds_2_to_1[0], &sock1, &net1);
359 t2 = std::thread(&sock_read_data_thread, pipefds_1_to_2[0], &sock2, &net2);
361 // Note that we have to bind the result to a C++ class to make sure it gets free'd
362 LDK::CResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(&net1, ChannelManager_get_our_node_id(&cm2), sock1, COption_SocketAddressZ_none());
363 assert(con_res->result_ok);
364 LDK::CResult_NonePeerHandleErrorZ con_res2 = PeerManager_new_inbound_connection(&net2, sock2, COption_SocketAddressZ_none());
365 assert(con_res2->result_ok);
367 auto writelen = write(pipefds_1_to_2[1], con_res->contents.result->data, con_res->contents.result->datalen);
368 assert(writelen > 0 && uint64_t(writelen) == con_res->contents.result->datalen);
370 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
372 // Wait for the initial handshakes to complete...
373 LDK::CVec_PeerDetailsZ peers_1 = PeerManager_list_peers(&net1);
374 LDK::CVec_PeerDetailsZ peers_2 = PeerManager_list_peers(&net2);
375 if (peers_1->datalen == 1 && peers_2->datalen ==1) { break; }
376 std::this_thread::yield();
378 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
382 close(pipefds_1_to_2[0]);
383 close(pipefds_2_to_1[0]);
384 close(pipefds_1_to_2[1]);
385 close(pipefds_2_to_1[1]);
392 struct CustomOnionMsgQueue {
394 std::vector<LDK::OnionMessageContents> msgs;
397 uint64_t custom_onion_msg_type_id(const void *this_arg) {
400 LDKCVec_u8Z custom_onion_msg_bytes(const void *this_arg) {
401 uint8_t *bytes = (uint8_t *) malloc(1024);
402 memset(bytes, 43, 1024);
404 .data = bytes, .datalen = 1024
407 LDKStr custom_onion_msg_str(const void *this_arg) {
409 .chars = (const uint8_t*)"Custom Onion Message",
410 .len = 20, .chars_is_owned = false
414 LDKCOption_OnionMessageContentsZ handle_custom_onion_message(const void* this_arg, struct LDKOnionMessageContents msg) {
415 CustomOnionMsgQueue* arg = (CustomOnionMsgQueue*) this_arg;
416 std::unique_lock<std::mutex> lck(arg->mtx);
417 arg->msgs.push_back(std::move(msg));
418 return COption_OnionMessageContentsZ_none();
421 LDKOnionMessageContents build_custom_onion_message() {
422 return LDKOnionMessageContents {
424 .tlv_type = custom_onion_msg_type_id,
425 .write = custom_onion_msg_bytes,
426 .debug_str = custom_onion_msg_str,
432 LDKCResult_COption_OnionMessageContentsZDecodeErrorZ read_custom_onion_message(const void* this_arg, uint64_t type, LDKu8slice buf) {
433 assert(type == 8888);
434 assert(buf.datalen == 1024);
436 memset(cmp, 43, 1024);
437 assert(!memcmp(cmp, buf.data, 1024));
438 return CResult_COption_OnionMessageContentsZDecodeErrorZ_ok(COption_OnionMessageContentsZ_some(build_custom_onion_message()));
441 LDKCVec_C3Tuple_OnionMessageContentsDestinationBlindedPathZZ release_no_messages(const void* this_arg) {
442 return LDKCVec_C3Tuple_OnionMessageContentsDestinationBlindedPathZZ {
443 .data = NULL, .datalen = 0 };
446 struct CustomMsgQueue {
447 std::vector<LDK::Type> msgs;
450 uint16_t custom_msg_type_id(const void *this_arg) {
453 LDKCVec_u8Z custom_msg_bytes(const void *this_arg) {
454 uint8_t *bytes = (uint8_t *) malloc(1024);
455 memset(bytes, 42, 1024);
457 .data = bytes, .datalen = 1024
460 LDKStr custom_msg_debug(const void *this_arg) {
462 .chars = (const unsigned char*) "Custom Message", .len = 14, .chars_is_owned = false
466 LDKCResult_COption_TypeZDecodeErrorZ read_custom_message(const void* this_arg, uint16_t type_id, LDKu8slice buf) {
467 assert(type_id == 8888);
468 assert(buf.datalen == 1024);
470 memset(cmp, 42, 1024);
471 assert(!memcmp(cmp, buf.data, 1024));
472 return CResult_COption_TypeZDecodeErrorZ_ok(COption_TypeZ_some(LDKType {
474 .type_id = custom_msg_type_id,
475 .debug_str = custom_msg_debug,
476 .write = NULL, // This message should never be written
481 LDKCResult_NoneLightningErrorZ handle_custom_message(const void* this_arg, struct LDKType msg, struct LDKPublicKey _sender_node_id) {
482 CustomMsgQueue* arg = (CustomMsgQueue*) this_arg;
483 arg->msgs.push_back(std::move(msg));
484 return CResult_NoneLightningErrorZ_ok();
486 LDKCVec_C2Tuple_PublicKeyTypeZZ never_send_custom_msgs(const void* this_arg) {
487 return LDKCVec_C2Tuple_PublicKeyTypeZZ {
488 .data = NULL, .datalen = 0
492 LDKCVec_C2Tuple_PublicKeyTypeZZ create_custom_msg(const void* this_arg) {
493 const LDKPublicKey *counterparty_node_id = (const LDKPublicKey *)this_arg;
494 LDKCVec_C2Tuple_PublicKeyTypeZZ ret = {
495 .data = ((LDKC2Tuple_PublicKeyTypeZ*)malloc(sizeof(LDKC2Tuple_PublicKeyTypeZ))),
498 ret.data[0].a = *counterparty_node_id;
499 ret.data[0].b = LDKType {
501 .type_id = custom_msg_type_id,
502 .debug_str = custom_msg_debug,
503 .write = custom_msg_bytes,
509 LDKNodeFeatures custom_node_features(const void *this_arg) {
510 return NodeFeatures_empty();
513 LDKInitFeatures custom_init_features(const void *this_arg, struct LDKPublicKey their_node_id) {
514 return InitFeatures_empty();
517 uint64_t get_chan_score(const void *this_arg, const LDKCandidateRouteHop *hop, LDKChannelUsage usage_in, const LDKProbabilisticScoringFeeParameters *params) {
518 LDK::ChannelUsage usage(std::move(usage_in));
522 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) {
523 const LDK::DefaultRouter *router = (LDK::DefaultRouter *)this_arg;
524 assert(first_hops->datalen == 1);
525 assert(ChannelDetails_get_is_usable(&first_hops->data[0]));
526 const LDK::Router router_impl = DefaultRouter_as_Router(&*router);
527 return router_impl->find_route(router_impl->this_arg, payer, route_params, first_hops, in_flights);
531 uint8_t channel_open_header[80];
532 uint8_t header_1[80];
533 uint8_t header_2[80];
534 memcpy(channel_open_header, channel_open_block, 80);
535 memcpy(header_1, block_1, 80);
536 memcpy(header_2, block_2, 80);
538 LDKPublicKey null_pk;
539 memset(&null_pk, 0, sizeof(null_pk));
541 LDKThirtyTwoBytes random_bytes;
542 LDKThirtyTwoBytes chain_tip;
543 memset(&chain_tip, 0, sizeof(chain_tip)); // channel_open_header's prev_blockhash is all-0s
545 LDKNetwork network = LDKNetwork_Testnet;
547 // Trait implementations:
548 LDKBroadcasterInterface broadcast {
550 .broadcast_transactions = broadcast_txn,
554 // Instantiate classes for the nodes that don't get reloaded on a ser-des reload
556 .this_arg = (void*)1,
562 mons1.logger = &logger1;
565 .watch_channel = add_channel_monitor,
566 .update_channel = update_channel_monitor,
567 .release_pending_monitor_events = monitors_pending_monitor_events,
571 LDK::NetworkGraph net_graph1 = NetworkGraph_new(network, logger1);
572 LDK::P2PGossipSync graph_msg_handler1 = P2PGossipSync_new(&net_graph1, COption_UtxoLookupZ_none(), logger1);
575 .this_arg = (void*)2,
581 mons2.logger = &logger2;
584 .watch_channel = add_channel_monitor,
585 .update_channel = update_channel_monitor,
586 .release_pending_monitor_events = monitors_pending_monitor_events,
590 LDKRouter panic_router = {
592 .find_route = NULL, // Segfault if we ever try to find a route
593 .find_route_with_id = NULL, // Segfault if we ever try to find a route
597 LDK::NetworkGraph net_graph2 = NetworkGraph_new(network, logger2);
598 LDK::P2PGossipSync graph_msg_handler2 = P2PGossipSync_new(&net_graph2, COption_UtxoLookupZ_none(), logger2);
600 LDK::CVec_u8Z cm1_ser = LDKCVec_u8Z {}; // ChannelManager 1 serialization at the end of the ser-des scope
601 LDK::CVec_u8Z cm2_ser = LDKCVec_u8Z {}; // ChannelManager 2 serialization at the end of the ser-des scope
603 { // Scope for the ser-des reload
604 // Instantiate classes for node 1:
605 uint8_t node_seed[32];
606 memset(&node_seed, 0, 32);
607 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 0, 0);
608 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
609 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
610 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
612 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)), 1689638400);
614 LDK::IgnoringMessageHandler ignoring_handler1 = IgnoringMessageHandler_new();
615 LDK::CustomMessageHandler custom_msg_handler1 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler1);
616 LDK::CustomOnionMessageHandler custom_onion_msg_handler1 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler1);
617 LDK::DefaultMessageRouter mr1 = DefaultMessageRouter_new(&net_graph1, KeysManager_as_EntropySource(&keys1));
618 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, ChannelManager_as_NodeIdLookUp(&cm1), DefaultMessageRouter_as_MessageRouter(&mr1), IgnoringMessageHandler_as_OffersMessageHandler(&ignoring_handler1), std::move(custom_onion_msg_handler1));
620 LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
621 assert(channels->datalen == 0);
623 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler1), OnionMessenger_as_OnionMessageHandler(&om1), std::move(custom_msg_handler1));
625 random_bytes = entropy_source1.get_secure_random_bytes();
626 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(node_signer1));
628 // Demo getting a channel key and check that its returning real pubkeys:
629 LDKSixteenBytes user_id_1 { .data = {45, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0} };
630 LDKThirtyTwoBytes chan_signer_id1 = signer_provider1.generate_channel_keys_id(false, 42, U128_new(user_id_1));
631 LDK::WriteableEcdsaChannelSigner chan_signer1 = signer_provider1.derive_channel_signer(42, chan_signer_id1);
632 chan_signer1->EcdsaChannelSigner.ChannelSigner.set_pubkeys(&chan_signer1->EcdsaChannelSigner.ChannelSigner); // Make sure pubkeys is defined
633 LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->EcdsaChannelSigner.ChannelSigner.pubkeys);
634 assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
636 // Instantiate classes for node 2:
637 memset(&node_seed, 1, 32);
638 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 0, 0);
639 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
640 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
641 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
643 LDK::ChannelHandshakeConfig handshake_config2 = ChannelHandshakeConfig_default();
644 ChannelHandshakeConfig_set_minimum_depth(&handshake_config2, 2);
645 LDK::UserConfig config2 = UserConfig_default();
646 UserConfig_set_channel_handshake_config(&config2, std::move(handshake_config2));
648 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)), 1689638400);
650 LDK::IgnoringMessageHandler ignoring_handler2 = IgnoringMessageHandler_new();
651 LDK::CustomMessageHandler custom_msg_handler2 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler2);
652 LDK::CustomOnionMessageHandler custom_onion_msg_handler2 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler2);
653 LDK::DefaultMessageRouter mr2 = DefaultMessageRouter_new(&net_graph2, KeysManager_as_EntropySource(&keys2));
654 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, ChannelManager_as_NodeIdLookUp(&cm2), DefaultMessageRouter_as_MessageRouter(&mr2), IgnoringMessageHandler_as_OffersMessageHandler(&ignoring_handler2), std::move(custom_onion_msg_handler2));
656 LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
657 assert(channels2->datalen == 0);
659 LDK::RoutingMessageHandler net_msgs2 = P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2);
660 LDK::CResult_ChannelAnnouncementDecodeErrorZ chan_ann = ChannelAnnouncement_read(LDKu8slice { .data = valid_node_announcement, .datalen = sizeof(valid_node_announcement) });
661 assert(chan_ann->result_ok);
662 LDK::CResult_boolLightningErrorZ ann_res = net_msgs2->handle_channel_announcement(net_msgs2->this_arg, chan_ann->contents.result);
663 assert(ann_res->result_ok);
665 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), std::move(net_msgs2), OnionMessenger_as_OnionMessageHandler(&om1), std::move(custom_msg_handler2));
667 random_bytes = entropy_source2.get_secure_random_bytes();
668 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(node_signer2));
670 // Open a connection!
671 PeersConnection conn(cm1, cm2, net1, net2);
673 // Note that we have to bind the result to a C++ class to make sure it gets free'd
674 LDK::CResult_ChannelIdAPIErrorZ res = ChannelManager_create_channel(&cm1, ChannelManager_get_our_node_id(&cm2), 40000, 1000, U128_new(user_id_1), LDKChannelId { .inner = NULL, .is_owned = false }, UserConfig_default());
675 assert(res->result_ok);
676 PeerManager_process_events(&net1);
678 LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
679 assert(new_channels->datalen == 1);
680 LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
681 LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
682 assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
684 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting first channel..." << std::endl;
686 LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
687 if (new_channels_2->datalen == 1) {
688 // Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
689 LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
690 const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
691 assert(init_feats->inner != NULL);
694 std::this_thread::yield();
696 std::cout << __FILE__ << ":" << __LINE__ << " - " << "First channel listed!" << std::endl;
698 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
699 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting FundingGenerationReady event..." << std::endl;
702 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
703 ev1.process_pending_events(handler);
704 if (queue.events.size() == 1) {
705 assert(queue.events[0]->tag == LDKEvent_FundingGenerationReady);
706 LDKSixteenBytes event_id = U128_le_bytes(queue.events[0]->funding_generation_ready.user_channel_id);
707 assert(!memcmp(&event_id, &user_id_1, 16));
708 assert(queue.events[0]->funding_generation_ready.channel_value_satoshis == 40000);
709 assert(queue.events[0]->funding_generation_ready.output_script.datalen == 34);
711 assert(!memcmp(queue.events[0]->funding_generation_ready.output_script.data, channel_open_block + 58 + 81, 34));
712 LDKTransaction funding_transaction { .data = const_cast<uint8_t*>(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false };
714 LDK::CResult_NoneAPIErrorZ fund_res = ChannelManager_funding_transaction_generated(&cm1, &queue.events[0]->funding_generation_ready.temporary_channel_id, queue.events[0]->funding_generation_ready.counterparty_node_id, funding_transaction);
715 assert(fund_res->result_ok);
718 std::this_thread::yield();
720 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received FundingGenerationReady event!" << std::endl;
722 // We observe when the funding signed messages have been exchanged by
723 // waiting for two monitors to be registered.
724 assert(num_txs_broadcasted == 0);
725 PeerManager_process_events(&net1);
726 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting transaction broadcast..." << std::endl;
727 while (num_txs_broadcasted != 1) {
728 std::this_thread::yield();
730 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Transaction was broadcast!" << std::endl;
732 // Note that the channel ID is the same as the channel txid reversed as the output index is 0
733 uint8_t expected_chan_id[32];
734 for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
736 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
739 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
740 ev1.process_pending_events(handler);
741 if (queue.events.size() == 1) {
742 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
743 assert(!memcmp(ChannelId_get_a(&queue.events[0]->channel_pending.channel_id), expected_chan_id, 32));
746 std::this_thread::yield();
748 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
750 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
751 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
754 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
755 ev2.process_pending_events(handler);
756 if (queue.events.size() == 1) {
757 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
758 assert(!memcmp(ChannelId_get_a(&queue.events[0]->channel_pending.channel_id), expected_chan_id, 32));
761 std::this_thread::yield();
763 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
765 LDK::Listen listener1 = ChannelManager_as_Listen(&cm1);
766 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
768 LDK::Listen listener2 = ChannelManager_as_Listen(&cm2);
769 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
771 LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
772 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
773 mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
775 txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
776 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
777 mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
779 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
780 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
781 mons1.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
782 mons2.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
784 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
785 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
786 mons1.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
787 mons2.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
789 PeerManager_process_events(&net1);
790 PeerManager_process_events(&net2);
792 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
795 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
796 ev2.process_pending_events(handler);
797 if (queue.events.size() == 1) {
798 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
799 assert(!memcmp(ChannelId_get_a(&queue.events[0]->channel_ready.channel_id), expected_chan_id, 32));
802 std::this_thread::yield();
804 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
806 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
809 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
810 ev1.process_pending_events(handler);
811 if (queue.events.size() == 1) {
812 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
813 assert(!memcmp(ChannelId_get_a(&queue.events[0]->channel_ready.channel_id), expected_chan_id, 32));
816 std::this_thread::yield();
818 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
820 // Now send funds from 1 to 2!
821 uint64_t channel_scid;
822 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
824 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
825 if (outbound_channels->datalen == 1) {
826 const LDKChannelDetails *channel = &outbound_channels->data[0];
827 LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
829 LDK::ChannelId chan_id = ChannelDetails_get_channel_id(channel);
830 assert(!memcmp(ChannelId_get_a(&chan_id), expected_chan_id, 32));
832 ChannelCounterparty_get_node_id(&counterparty).compressed_form,
833 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
834 assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
835 // We opened the channel with 1000 push_msat:
836 assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
837 40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
838 int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
839 if (inbound_capacity < 0) inbound_capacity = 0;
840 assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
841 assert(ChannelDetails_get_is_usable(channel));
842 LDK::COption_u64Z scid_opt = ChannelDetails_get_short_channel_id(channel);
843 assert(scid_opt->some);
844 channel_scid = scid_opt->some;
847 std::this_thread::yield();
849 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
851 LDKCOption_u64Z min_value = {
852 .tag = LDKCOption_u64Z_Some,
855 LDK::CResult_Bolt11InvoiceSignOrCreationErrorZ invoice = create_invoice_from_channelmanager(&cm2,
856 KeysManager_as_NodeSigner(&keys2), logger2,
857 LDKCurrency_Bitcoin, min_value,
859 .chars = (const uint8_t *)"Invoice Description",
860 .len = strlen("Invoice Description"),
861 .chars_is_owned = false
862 }, 3600, COption_u16Z_none());
863 assert(invoice->result_ok);
864 LDKThirtyTwoBytes payment_hash;
865 memcpy(payment_hash.data, Bolt11Invoice_payment_hash(invoice->contents.result), 32);
868 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
869 LDK::ScoreLookUp chan_scorer = LDKScoreLookUp {
870 .this_arg = NULL, .channel_penalty_msat = get_chan_score, .free = NULL,
872 LDK::Payee payee = Payee_clear(ChannelManager_get_our_node_id(&cm2), Bolt11Invoice_route_hints(invoice->contents.result),
873 LDKBolt11InvoiceFeatures {
874 .inner = NULL, .is_owned = false
875 }, Bolt11Invoice_min_final_cltv_expiry_delta(invoice->contents.result));
876 LDK::RouteParameters route_params = RouteParameters_from_payment_params_and_value(
877 PaymentParameters_new(std::move(payee), COption_u64Z_none(), 0xffffffff, 1, 2,
878 LDKCVec_u64Z { .data = NULL, .datalen = 0 }, LDKCVec_u64Z { .data = NULL, .datalen = 0 }),
880 random_bytes = entropy_source1.get_secure_random_bytes();
881 LDK::ProbabilisticScoringFeeParameters params = ProbabilisticScoringFeeParameters_default();
883 LDK::CResult_RouteLightningErrorZ route = find_route(ChannelManager_get_our_node_id(&cm1), &route_params, &net_graph2, &outbound_channels, logger1, &chan_scorer, ¶ms, &random_bytes.data);
885 assert(route->result_ok);
886 LDK::CVec_PathZ paths = Route_get_paths(route->contents.result);
887 assert(paths->datalen == 1);
888 LDK::CVec_RouteHopZ hops = Path_get_hops(&paths->data[0]);
889 assert(hops->datalen == 1);
890 assert(!memcmp(RouteHop_get_pubkey(&hops->data[0]).compressed_form,
891 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
892 assert(RouteHop_get_short_channel_id(&hops->data[0]) == channel_scid);
893 LDKThirtyTwoBytes payment_secret;
894 memcpy(payment_secret.data, Bolt11Invoice_payment_secret(invoice->contents.result), 32);
895 LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment_with_route(&cm1,
896 route->contents.result, payment_hash, RecipientOnionFields_secret_only(payment_secret), payment_hash);
897 assert(send_res->result_ok);
901 PeerManager_process_events(&net1);
902 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 4 updated monitors..." << std::endl;
903 while (mons_updated != 4) {
904 std::this_thread::yield();
906 std::cout << __FILE__ << ":" << __LINE__ << " - " << "4 monitors updated!" << std::endl;
908 // Check that we received the payment!
909 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
912 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
913 ev2.process_pending_events(handler);
914 if (queue.events.size() == 1) {
915 assert(queue.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
918 std::this_thread::yield();
920 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
921 ChannelManager_process_pending_htlc_forwards(&cm2);
922 PeerManager_process_events(&net2);
925 LDKThirtyTwoBytes payment_preimage;
928 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
929 ev2.process_pending_events(handler);
930 assert(queue.events.size() == 1);
931 assert(queue.events[0]->tag == LDKEvent_PaymentClaimable);
932 assert(!memcmp(queue.events[0]->payment_claimable.payment_hash.data, payment_hash.data, 32));
933 assert(queue.events[0]->payment_claimable.purpose.tag == LDKPaymentPurpose_Bolt11InvoicePayment);
934 assert(!memcmp(queue.events[0]->payment_claimable.purpose.bolt11_invoice_payment.payment_secret.data,
935 Bolt11Invoice_payment_secret(invoice->contents.result), 32));
936 assert(queue.events[0]->payment_claimable.amount_msat == 5000);
937 assert(queue.events[0]->payment_claimable.purpose.bolt11_invoice_payment.payment_preimage.tag == LDKCOption_ThirtyTwoBytesZ_Some);
938 memcpy(payment_preimage.data, queue.events[0]->payment_claimable.purpose.bolt11_invoice_payment.payment_preimage.some.data, 32);
939 ChannelManager_claim_funds(&cm2, payment_preimage);
941 queue.events.clear();
942 ev2.process_pending_events(handler);
943 assert(queue.events.size() == 1);
944 assert(queue.events[0]->tag == LDKEvent_PaymentClaimed);
945 assert(!memcmp(queue.events[0]->payment_claimed.payment_hash.data, payment_hash.data, 32));
946 assert(queue.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_Bolt11InvoicePayment);
948 PeerManager_process_events(&net2);
949 // Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
952 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
953 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
954 while (queue.events.size() < 2) {
955 ev1.process_pending_events(handler);
956 std::this_thread::yield();
958 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
959 assert(queue.events.size() == 2);
960 assert(queue.events[0]->tag == LDKEvent_PaymentSent);
961 assert(!memcmp(queue.events[0]->payment_sent.payment_preimage.data, payment_preimage.data, 32));
962 assert(queue.events[1]->tag == LDKEvent_PaymentPathSuccessful);
963 assert(queue.events[1]->payment_path_successful.payment_hash.tag == LDKCOption_ThirtyTwoBytesZ_Some);
964 assert(!memcmp(queue.events[1]->payment_path_successful.payment_hash.some.data, payment_hash.data, 32));
966 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 5 updated monitors..." << std::endl;
967 while (mons_updated != 5) {
968 std::this_thread::yield();
970 std::cout << __FILE__ << ":" << __LINE__ << " - " << "5 monitors updated!" << std::endl;
974 cm1_ser = ChannelManager_write(&cm1);
975 cm2_ser = ChannelManager_write(&cm2);
978 LDK::CVec_ChannelMonitorZ mons_list1 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
979 assert(mons1.mons.size() == 1);
980 mons_list1->data[0] = *& std::get<1>(mons1.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
981 mons_list1->data[0].is_owned = false; // XXX: God this sucks
982 uint8_t node_seed[32];
983 memset(&node_seed, 0, 32);
984 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 1, 0);
985 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
986 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
987 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
989 LDK::ProbabilisticScorer scorer1 = ProbabilisticScorer_new(ProbabilisticScoringDecayParameters_default(), &net_graph1, logger1);
990 LDK::Score scorer_trait1 = ProbabilisticScorer_as_Score(&scorer1);
991 LDK::MultiThreadedLockableScore scorer_mtx1 = MultiThreadedLockableScore_new(std::move(scorer_trait1));
992 LDK::LockableScore scorer_mtx_trait1 = MultiThreadedLockableScore_as_LockableScore(&scorer_mtx1);
993 LDK::ProbabilisticScoringFeeParameters params = ProbabilisticScoringFeeParameters_default();
994 const LDK::DefaultRouter default_router_1 = DefaultRouter_new(&net_graph1, logger1, KeysManager_as_EntropySource(&keys1), std::move(scorer_mtx_trait1), std::move(params));
995 LDKRouter router1 = {
996 .this_arg = (void*)&default_router_1,
997 .find_route = NULL, // LDK currently doesn't use this, its just a default-impl
998 .find_route_with_id = custom_find_route,
1002 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));
1003 LDK::CResult_C2Tuple_ThirtyTwoBytesChannelManagerZDecodeErrorZ cm1_read =
1004 C2Tuple_ThirtyTwoBytesChannelManagerZ_read(LDKu8slice { .data = cm1_ser->data, .datalen = cm1_ser -> datalen}, std::move(cm1_args));
1005 assert(cm1_read->result_ok);
1006 LDK::ChannelManager cm1(std::move(cm1_read->contents.result->b));
1008 LDKCustomOnionMessageHandler custom_onion_msg_handler1 = {
1010 .handle_custom_message = NULL, // We only create custom messages, not handle them
1011 .read_custom_message = NULL, // We only create custom messages, not handle them
1012 .release_pending_custom_messages = release_no_messages,
1015 LDK::DefaultMessageRouter mr1 = DefaultMessageRouter_new(&net_graph1, KeysManager_as_EntropySource(&keys1));
1016 LDK::IgnoringMessageHandler ignorer_1 = IgnoringMessageHandler_new();
1017 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, ChannelManager_as_NodeIdLookUp(&cm1), DefaultMessageRouter_as_MessageRouter(&mr1), IgnoringMessageHandler_as_OffersMessageHandler(&ignorer_1), std::move(custom_onion_msg_handler1));
1019 LDK::CVec_ChannelMonitorZ mons_list2 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
1020 assert(mons2.mons.size() == 1);
1021 mons_list2->data[0] = *& std::get<1>(mons2.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
1022 mons_list2->data[0].is_owned = false; // XXX: God this sucks
1023 memset(&node_seed, 1, 32);
1024 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 1, 0);
1025 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
1026 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
1027 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
1029 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));
1030 LDK::CResult_C2Tuple_ThirtyTwoBytesChannelManagerZDecodeErrorZ cm2_read =
1031 C2Tuple_ThirtyTwoBytesChannelManagerZ_read(LDKu8slice { .data = cm2_ser->data, .datalen = cm2_ser -> datalen}, std::move(cm2_args));
1032 assert(cm2_read->result_ok);
1033 LDK::ChannelManager cm2(std::move(cm2_read->contents.result->b));
1035 CustomOnionMsgQueue peer_2_custom_onion_messages;
1036 LDKCustomOnionMessageHandler custom_onion_msg_handler2 = {
1037 .this_arg = &peer_2_custom_onion_messages,
1038 .handle_custom_message = handle_custom_onion_message,
1039 .read_custom_message = read_custom_onion_message,
1040 .release_pending_custom_messages = release_no_messages,
1043 LDK::DefaultMessageRouter mr2 = DefaultMessageRouter_new(&net_graph2, KeysManager_as_EntropySource(&keys2));
1044 LDK::IgnoringMessageHandler ignorer_2 = IgnoringMessageHandler_new();
1045 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, ChannelManager_as_NodeIdLookUp(&cm2), DefaultMessageRouter_as_MessageRouter(&mr2), IgnoringMessageHandler_as_OffersMessageHandler(&ignorer_2), custom_onion_msg_handler2);
1047 // Attempt to close the channel...
1048 LDKThirtyTwoBytes chan_id_bytes;
1049 for (int i = 0; i < 32; i++) { chan_id_bytes.data[i] = channel_open_txid[31-i]; }
1050 LDK::ChannelId chan_id = ChannelId_new(chan_id_bytes);
1051 LDK::CResult_NoneAPIErrorZ close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1052 assert(!close_res->result_ok); // Note that we can't close while disconnected!
1054 // Open a connection!
1055 LDKPublicKey chan_2_node_id = ChannelManager_get_our_node_id(&cm2);
1056 LDKCustomMessageHandler custom_msg_handler1 = {
1057 .this_arg = &chan_2_node_id,
1058 .handle_custom_message = NULL, // We only create custom messages, not handle them
1059 .get_and_clear_pending_msg = create_custom_msg,
1060 .provided_node_features = custom_node_features,
1061 .provided_init_features = custom_init_features,
1062 .CustomMessageReader = LDKCustomMessageReader {
1064 .read = read_custom_message,
1069 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler1), OnionMessenger_as_OnionMessageHandler(&om1), custom_msg_handler1);
1070 random_bytes = entropy_source1.get_secure_random_bytes();
1071 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(node_signer1));
1073 CustomMsgQueue peer_2_custom_messages;
1074 LDKCustomMessageHandler custom_msg_handler2 = {
1075 .this_arg = &peer_2_custom_messages,
1076 .handle_custom_message = handle_custom_message,
1077 .get_and_clear_pending_msg = never_send_custom_msgs,
1078 .provided_node_features = custom_node_features,
1079 .provided_init_features = custom_init_features,
1080 .CustomMessageReader = LDKCustomMessageReader {
1082 .read = read_custom_message,
1087 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2), OnionMessenger_as_OnionMessageHandler(&om2), custom_msg_handler2);
1088 random_bytes = entropy_source1.get_secure_random_bytes();
1089 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(node_signer2));
1091 PeersConnection conn(cm1, cm2, net1, net2);
1093 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
1095 // Wait for the channels to be considered up once the reestablish messages are processed
1096 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
1097 if (outbound_channels->datalen == 1) {
1100 std::this_thread::yield();
1102 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
1104 // Send another payment, this time via the retires path
1105 LDK::CResult_Bolt11InvoiceSignOrCreationErrorZ invoice_res2 = create_invoice_from_channelmanager(&cm2,
1106 KeysManager_as_NodeSigner(&keys2), logger1,
1107 LDKCurrency_Bitcoin, COption_u64Z_some(10000),
1109 .chars = (const uint8_t *)"Invoice 2 Description",
1110 .len = strlen("Invoice 2 Description"),
1111 .chars_is_owned = false
1112 }, 3600, COption_u16Z_none());
1113 assert(invoice_res2->result_ok);
1114 const LDKBolt11Invoice *invoice2 = invoice_res2->contents.result;
1115 LDK::CResult_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ pay_params =
1116 payment_parameters_from_invoice(invoice2);
1117 LDK::RecipientOnionFields invoice2_recipient(std::move(pay_params->contents.result->b));
1118 LDK::RouteParameters invoice2_params(std::move(pay_params->contents.result->c));
1119 assert(pay_params->result_ok);
1120 LDKThirtyTwoBytes payment_id;
1121 memset(&payment_id, 0, 32);
1122 LDK::CResult_NoneRetryableSendFailureZ invoice_pay_res = ChannelManager_send_payment(
1123 &cm1, std::move(pay_params->contents.result->a), std::move(invoice2_recipient),
1124 std::move(payment_id), std::move(invoice2_params), Retry_attempts(0)
1126 assert(invoice_pay_res->result_ok);
1127 PeerManager_process_events(&net1);
1129 // Check that we received the payment!
1130 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
1133 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1134 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1135 ev2.process_pending_events(handler2);
1136 if (queue2.events.size() == 1) {
1137 assert(queue2.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
1140 std::this_thread::yield();
1142 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
1143 ChannelManager_process_pending_htlc_forwards(&cm2);
1144 PeerManager_process_events(&net2);
1146 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentClaimable/PaymentClaimed event..." << std::endl;
1149 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1150 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1151 ev2.process_pending_events(handler2);
1152 if (queue2.events.size() == 1) {
1153 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimable);
1154 const struct LDKEvent_LDKPaymentClaimable_Body *event_data = &queue2.events[0]->payment_claimable;
1155 assert(!memcmp(event_data->payment_hash.data, Bolt11Invoice_payment_hash(invoice2), 32));
1156 assert(event_data->purpose.tag == LDKPaymentPurpose_Bolt11InvoicePayment);
1157 assert(!memcmp(event_data->purpose.bolt11_invoice_payment.payment_secret.data,
1158 Bolt11Invoice_payment_secret(invoice2), 32));
1159 assert(event_data->amount_msat == 10000);
1160 assert(event_data->purpose.bolt11_invoice_payment.payment_preimage.tag == LDKCOption_ThirtyTwoBytesZ_Some);
1161 ChannelManager_claim_funds(&cm2, event_data->purpose.bolt11_invoice_payment.payment_preimage.some);
1163 queue2.events.clear();
1164 ev2.process_pending_events(handler2);
1165 assert(queue2.events.size() == 1);
1166 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimed);
1167 assert(!memcmp(queue2.events[0]->payment_claimed.payment_hash.data, Bolt11Invoice_payment_hash(invoice2), 32));
1168 assert(queue2.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_Bolt11InvoicePayment);
1172 std::this_thread::yield();
1174 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentClaimable/PaymentClaimed event!" << std::endl;
1177 LDKEventHandler handler1 = { .this_arg = &queue1, .handle_event = handle_event, .free = NULL };
1178 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
1179 while (queue1.events.size() < 2) {
1180 PeerManager_process_events(&net2);
1181 PeerManager_process_events(&net1);
1183 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
1184 ev1.process_pending_events(handler1);
1185 std::this_thread::yield();
1187 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
1188 assert(queue1.events.size() == 2);
1189 assert(queue1.events[0]->tag == LDKEvent_PaymentSent);
1190 assert(queue1.events[1]->tag == LDKEvent_PaymentPathSuccessful);
1192 // Actually close the channel
1193 num_txs_broadcasted = 0;
1194 close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1195 assert(close_res->result_ok);
1196 PeerManager_process_events(&net1);
1197 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 2 transaction broadcasts..." << std::endl;
1198 while (num_txs_broadcasted != 2) {
1199 std::this_thread::yield();
1201 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Broadcast 2 transactions!" << std::endl;
1202 LDK::CVec_ChannelDetailsZ chans_after_close1 = ChannelManager_list_channels(&cm1);
1203 assert(chans_after_close1->datalen == 0);
1204 LDK::CVec_ChannelDetailsZ chans_after_close2 = ChannelManager_list_channels(&cm2);
1205 assert(chans_after_close2->datalen == 0);
1207 LDK::CResult_SendSuccessSendErrorZ om_send_res =
1208 OnionMessenger_send_onion_message(&om1,
1209 build_custom_onion_message(),
1210 Destination_node(ChannelManager_get_our_node_id(&cm2)),
1211 LDKBlindedPath { .inner = NULL, .is_owned = true });
1212 assert(om_send_res->result_ok);
1213 PeerManager_process_events(&net1);
1214 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting onion message..." << std::endl;
1216 std::this_thread::yield();
1217 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1218 if (peer_2_custom_onion_messages.msgs.size() != 0) break;
1220 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received onion message!" << std::endl;
1224 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1225 assert(peer_2_custom_onion_messages.msgs.size() == 1);
1226 assert(peer_2_custom_onion_messages.msgs[0].tlv_type() == 8888);
1227 assert(peer_2_custom_messages.msgs.size() != 0);
1229 // Few extra random tests:
1231 memset(&sk, 42, 32);
1232 LDKThirtyTwoBytes kdiv_params;
1233 memset(&kdiv_params, 43, 32);
1234 LDK::InMemorySigner signer = InMemorySigner_new(sk, sk, sk, sk, sk, random_bytes, 42, kdiv_params, kdiv_params);