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_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_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 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_SocketAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
234 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ 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 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1));
247 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
249 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting new connection handshake..." << std::endl;
251 // Wait for the new connection handshake...
252 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
253 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
254 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
255 std::this_thread::yield();
257 std::cout << __FILE__ << ":" << __LINE__ << " - " << "New connection handshake complete!" << std::endl;
259 // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
260 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting peer disconnection..." << std::endl;
262 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2));
263 // Wait for the peers to disconnect...
264 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
265 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
266 if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
267 std::this_thread::yield();
269 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Peers disconnected!" << std::endl;
270 // Note that the above is somewhat race-y, as node 2 may still think its connected.
271 // Thus, make sure any connections are disconnected on its end as well.
272 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1));
274 // Finally make an actual connection and keep it this time
275 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
277 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
279 // Wait for the initial handshakes to complete...
280 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
281 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
282 if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
283 std::this_thread::yield();
285 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
288 interrupt_socket_handling(node1_handler);
289 interrupt_socket_handling(node2_handler);
295 uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
296 return write((int)((long)this_arg), data.data, data.datalen);
298 void sock_disconnect_socket(void *this_arg) {
299 close((int)((long)this_arg));
301 bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) {
302 return this_arg == other_arg->this_arg;
304 uint64_t sock_hash(const void *this_arg) {
305 return (uint64_t)this_arg;
307 void sock_read_data_thread(int rdfd, LDKSocketDescriptor *peer_descriptor, LDKPeerManager *pm) {
308 unsigned char buf[1024];
312 while ((readlen = read(rdfd, buf, 1024)) > 0) {
313 data.datalen = readlen;
314 LDK::CResult_boolPeerHandleErrorZ res = PeerManager_read_event(&*pm, peer_descriptor, data);
315 if (!res->result_ok) {
316 peer_descriptor->disconnect_socket(peer_descriptor->this_arg);
319 PeerManager_process_events(pm);
321 PeerManager_socket_disconnected(&*pm, peer_descriptor);
324 class PeersConnection {
325 int pipefds_1_to_2[2];
326 int pipefds_2_to_1[2];
328 LDKSocketDescriptor sock1, sock2;
331 PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
332 assert(!pipe(pipefds_1_to_2));
333 assert(!pipe(pipefds_2_to_1));
335 sock1 = LDKSocketDescriptor {
336 .this_arg = (void*)(long)pipefds_1_to_2[1],
337 .send_data = sock_send_data,
338 .disconnect_socket = sock_disconnect_socket,
345 sock2 = LDKSocketDescriptor {
346 .this_arg = (void*)(long)pipefds_2_to_1[1],
347 .send_data = sock_send_data,
348 .disconnect_socket = sock_disconnect_socket,
355 t1 = std::thread(&sock_read_data_thread, pipefds_2_to_1[0], &sock1, &net1);
356 t2 = std::thread(&sock_read_data_thread, pipefds_1_to_2[0], &sock2, &net2);
358 // Note that we have to bind the result to a C++ class to make sure it gets free'd
359 LDK::CResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(&net1, ChannelManager_get_our_node_id(&cm2), sock1, COption_SocketAddressZ_none());
360 assert(con_res->result_ok);
361 LDK::CResult_NonePeerHandleErrorZ con_res2 = PeerManager_new_inbound_connection(&net2, sock2, COption_SocketAddressZ_none());
362 assert(con_res2->result_ok);
364 auto writelen = write(pipefds_1_to_2[1], con_res->contents.result->data, con_res->contents.result->datalen);
365 assert(writelen > 0 && uint64_t(writelen) == con_res->contents.result->datalen);
367 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting initial handshake completion..." << std::endl;
369 // Wait for the initial handshakes to complete...
370 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_1 = PeerManager_get_peer_node_ids(&net1);
371 LDK::CVec_C2Tuple_PublicKeyCOption_SocketAddressZZZ peers_2 = PeerManager_get_peer_node_ids(&net2);
372 if (peers_1->datalen == 1 && peers_2->datalen ==1) { break; }
373 std::this_thread::yield();
375 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Initial handshake complete!" << std::endl;
379 close(pipefds_1_to_2[0]);
380 close(pipefds_2_to_1[0]);
381 close(pipefds_1_to_2[1]);
382 close(pipefds_2_to_1[1]);
389 struct CustomOnionMsgQueue {
391 std::vector<LDK::OnionMessageContents> msgs;
394 uint64_t custom_onion_msg_type_id(const void *this_arg) {
397 LDKCVec_u8Z custom_onion_msg_bytes(const void *this_arg) {
398 uint8_t *bytes = (uint8_t *) malloc(1024);
399 memset(bytes, 43, 1024);
401 .data = bytes, .datalen = 1024
404 LDKStr custom_onion_msg_str(const void *this_arg) {
406 .chars = (const uint8_t*)"Custom Onion Message",
407 .len = 20, .chars_is_owned = false
411 LDKCOption_OnionMessageContentsZ handle_custom_onion_message(const void* this_arg, struct LDKOnionMessageContents msg) {
412 CustomOnionMsgQueue* arg = (CustomOnionMsgQueue*) this_arg;
413 std::unique_lock<std::mutex> lck(arg->mtx);
414 arg->msgs.push_back(std::move(msg));
415 return COption_OnionMessageContentsZ_none();
418 LDKOnionMessageContents build_custom_onion_message() {
419 return LDKOnionMessageContents {
421 .tlv_type = custom_onion_msg_type_id,
422 .write = custom_onion_msg_bytes,
423 .debug_str = custom_onion_msg_str,
429 LDKCResult_COption_OnionMessageContentsZDecodeErrorZ read_custom_onion_message(const void* this_arg, uint64_t type, LDKu8slice buf) {
430 assert(type == 8888);
431 assert(buf.datalen == 1024);
433 memset(cmp, 43, 1024);
434 assert(!memcmp(cmp, buf.data, 1024));
435 return CResult_COption_OnionMessageContentsZDecodeErrorZ_ok(COption_OnionMessageContentsZ_some(build_custom_onion_message()));
438 LDKCVec_C3Tuple_OnionMessageContentsDestinationBlindedPathZZ release_no_messages(const void* this_arg) {
439 return LDKCVec_C3Tuple_OnionMessageContentsDestinationBlindedPathZZ {
440 .data = NULL, .datalen = 0 };
443 struct CustomMsgQueue {
444 std::vector<LDK::Type> msgs;
447 uint16_t custom_msg_type_id(const void *this_arg) {
450 LDKCVec_u8Z custom_msg_bytes(const void *this_arg) {
451 uint8_t *bytes = (uint8_t *) malloc(1024);
452 memset(bytes, 42, 1024);
454 .data = bytes, .datalen = 1024
457 LDKStr custom_msg_debug(const void *this_arg) {
459 .chars = (const unsigned char*) "Custom Message", .len = 14, .chars_is_owned = false
463 LDKCResult_COption_TypeZDecodeErrorZ read_custom_message(const void* this_arg, uint16_t type_id, LDKu8slice buf) {
464 assert(type_id == 8888);
465 assert(buf.datalen == 1024);
467 memset(cmp, 42, 1024);
468 assert(!memcmp(cmp, buf.data, 1024));
469 return CResult_COption_TypeZDecodeErrorZ_ok(COption_TypeZ_some(LDKType {
471 .type_id = custom_msg_type_id,
472 .debug_str = custom_msg_debug,
473 .write = NULL, // This message should never be written
478 LDKCResult_NoneLightningErrorZ handle_custom_message(const void* this_arg, struct LDKType msg, struct LDKPublicKey _sender_node_id) {
479 CustomMsgQueue* arg = (CustomMsgQueue*) this_arg;
480 arg->msgs.push_back(std::move(msg));
481 return CResult_NoneLightningErrorZ_ok();
483 LDKCVec_C2Tuple_PublicKeyTypeZZ never_send_custom_msgs(const void* this_arg) {
484 return LDKCVec_C2Tuple_PublicKeyTypeZZ {
485 .data = NULL, .datalen = 0
489 LDKCVec_C2Tuple_PublicKeyTypeZZ create_custom_msg(const void* this_arg) {
490 const LDKPublicKey *counterparty_node_id = (const LDKPublicKey *)this_arg;
491 LDKCVec_C2Tuple_PublicKeyTypeZZ ret = {
492 .data = ((LDKC2Tuple_PublicKeyTypeZ*)malloc(sizeof(LDKC2Tuple_PublicKeyTypeZ))),
495 ret.data[0].a = *counterparty_node_id;
496 ret.data[0].b = LDKType {
498 .type_id = custom_msg_type_id,
499 .debug_str = custom_msg_debug,
500 .write = custom_msg_bytes,
506 LDKNodeFeatures custom_node_features(const void *this_arg) {
507 return NodeFeatures_empty();
510 LDKInitFeatures custom_init_features(const void *this_arg, struct LDKPublicKey their_node_id) {
511 return InitFeatures_empty();
514 uint64_t get_chan_score(const void *this_arg, const LDKCandidateRouteHop *hop, LDKChannelUsage usage_in, const LDKProbabilisticScoringFeeParameters *params) {
515 LDK::ChannelUsage usage(std::move(usage_in));
519 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) {
520 const LDK::DefaultRouter *router = (LDK::DefaultRouter *)this_arg;
521 assert(first_hops->datalen == 1);
522 assert(ChannelDetails_get_is_usable(&first_hops->data[0]));
523 const LDK::Router router_impl = DefaultRouter_as_Router(&*router);
524 return router_impl->find_route(router_impl->this_arg, payer, route_params, first_hops, in_flights);
528 uint8_t channel_open_header[80];
529 uint8_t header_1[80];
530 uint8_t header_2[80];
531 memcpy(channel_open_header, channel_open_block, 80);
532 memcpy(header_1, block_1, 80);
533 memcpy(header_2, block_2, 80);
535 LDKPublicKey null_pk;
536 memset(&null_pk, 0, sizeof(null_pk));
538 LDKThirtyTwoBytes random_bytes;
539 LDKThirtyTwoBytes chain_tip;
540 memset(&chain_tip, 0, sizeof(chain_tip)); // channel_open_header's prev_blockhash is all-0s
542 LDKNetwork network = LDKNetwork_Testnet;
544 // Trait implementations:
545 LDKBroadcasterInterface broadcast {
547 .broadcast_transactions = broadcast_txn,
551 // Instantiate classes for the nodes that don't get reloaded on a ser-des reload
553 .this_arg = (void*)1,
559 mons1.logger = &logger1;
562 .watch_channel = add_channel_monitor,
563 .update_channel = update_channel_monitor,
564 .release_pending_monitor_events = monitors_pending_monitor_events,
568 LDK::NetworkGraph net_graph1 = NetworkGraph_new(network, logger1);
569 LDK::P2PGossipSync graph_msg_handler1 = P2PGossipSync_new(&net_graph1, COption_UtxoLookupZ_none(), logger1);
572 .this_arg = (void*)2,
578 mons2.logger = &logger2;
581 .watch_channel = add_channel_monitor,
582 .update_channel = update_channel_monitor,
583 .release_pending_monitor_events = monitors_pending_monitor_events,
587 LDKRouter panic_router = {
589 .find_route = NULL, // Segfault if we ever try to find a route
590 .find_route_with_id = NULL, // Segfault if we ever try to find a route
594 LDK::NetworkGraph net_graph2 = NetworkGraph_new(network, logger2);
595 LDK::P2PGossipSync graph_msg_handler2 = P2PGossipSync_new(&net_graph2, COption_UtxoLookupZ_none(), logger2);
597 LDK::CVec_u8Z cm1_ser = LDKCVec_u8Z {}; // ChannelManager 1 serialization at the end of the ser-des scope
598 LDK::CVec_u8Z cm2_ser = LDKCVec_u8Z {}; // ChannelManager 2 serialization at the end of the ser-des scope
600 { // Scope for the ser-des reload
601 // Instantiate classes for node 1:
602 uint8_t node_seed[32];
603 memset(&node_seed, 0, 32);
604 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 0, 0);
605 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
606 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
607 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
609 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);
611 LDK::IgnoringMessageHandler ignoring_handler1 = IgnoringMessageHandler_new();
612 LDK::CustomMessageHandler custom_msg_handler1 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler1);
613 LDK::CustomOnionMessageHandler custom_onion_msg_handler1 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler1);
614 LDK::DefaultMessageRouter mr1 = DefaultMessageRouter_new(&net_graph1, KeysManager_as_EntropySource(&keys1));
615 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, DefaultMessageRouter_as_MessageRouter(&mr1), IgnoringMessageHandler_as_OffersMessageHandler(&ignoring_handler1), std::move(custom_onion_msg_handler1));
617 LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
618 assert(channels->datalen == 0);
620 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));
622 random_bytes = entropy_source1.get_secure_random_bytes();
623 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(node_signer1));
625 // Demo getting a channel key and check that its returning real pubkeys:
626 LDKSixteenBytes user_id_1 { .data = {45, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0} };
627 LDKThirtyTwoBytes chan_signer_id1 = signer_provider1.generate_channel_keys_id(false, 42, U128_new(user_id_1));
628 LDK::WriteableEcdsaChannelSigner chan_signer1 = signer_provider1.derive_channel_signer(42, chan_signer_id1);
629 chan_signer1->EcdsaChannelSigner.ChannelSigner.set_pubkeys(&chan_signer1->EcdsaChannelSigner.ChannelSigner); // Make sure pubkeys is defined
630 LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->EcdsaChannelSigner.ChannelSigner.pubkeys);
631 assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
633 // Instantiate classes for node 2:
634 memset(&node_seed, 1, 32);
635 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 0, 0);
636 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
637 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
638 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
640 LDK::ChannelHandshakeConfig handshake_config2 = ChannelHandshakeConfig_default();
641 ChannelHandshakeConfig_set_minimum_depth(&handshake_config2, 2);
642 LDK::UserConfig config2 = UserConfig_default();
643 UserConfig_set_channel_handshake_config(&config2, std::move(handshake_config2));
645 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);
647 LDK::IgnoringMessageHandler ignoring_handler2 = IgnoringMessageHandler_new();
648 LDK::CustomMessageHandler custom_msg_handler2 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler2);
649 LDK::CustomOnionMessageHandler custom_onion_msg_handler2 = IgnoringMessageHandler_as_CustomOnionMessageHandler(&ignoring_handler2);
650 LDK::DefaultMessageRouter mr2 = DefaultMessageRouter_new(&net_graph2, KeysManager_as_EntropySource(&keys2));
651 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, DefaultMessageRouter_as_MessageRouter(&mr2), IgnoringMessageHandler_as_OffersMessageHandler(&ignoring_handler2), std::move(custom_onion_msg_handler2));
653 LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
654 assert(channels2->datalen == 0);
656 LDK::RoutingMessageHandler net_msgs2 = P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2);
657 LDK::CResult_ChannelAnnouncementDecodeErrorZ chan_ann = ChannelAnnouncement_read(LDKu8slice { .data = valid_node_announcement, .datalen = sizeof(valid_node_announcement) });
658 assert(chan_ann->result_ok);
659 LDK::CResult_boolLightningErrorZ ann_res = net_msgs2->handle_channel_announcement(net_msgs2->this_arg, chan_ann->contents.result);
660 assert(ann_res->result_ok);
662 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), std::move(net_msgs2), OnionMessenger_as_OnionMessageHandler(&om1), std::move(custom_msg_handler2));
664 random_bytes = entropy_source2.get_secure_random_bytes();
665 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(node_signer2));
667 // Open a connection!
668 PeersConnection conn(cm1, cm2, net1, net2);
670 // Note that we have to bind the result to a C++ class to make sure it gets free'd
671 LDK::CResult_ThirtyTwoBytesAPIErrorZ res = ChannelManager_create_channel(&cm1, ChannelManager_get_our_node_id(&cm2), 40000, 1000, U128_new(user_id_1), COption_ThirtyTwoBytesZ_none(), UserConfig_default());
672 assert(res->result_ok);
673 PeerManager_process_events(&net1);
675 LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
676 assert(new_channels->datalen == 1);
677 LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
678 LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
679 assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
681 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting first channel..." << std::endl;
683 LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
684 if (new_channels_2->datalen == 1) {
685 // Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
686 LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
687 const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
688 assert(init_feats->inner != NULL);
691 std::this_thread::yield();
693 std::cout << __FILE__ << ":" << __LINE__ << " - " << "First channel listed!" << std::endl;
695 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
696 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting FundingGenerationReady event..." << std::endl;
699 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
700 ev1.process_pending_events(handler);
701 if (queue.events.size() == 1) {
702 assert(queue.events[0]->tag == LDKEvent_FundingGenerationReady);
703 LDKSixteenBytes event_id = U128_le_bytes(queue.events[0]->funding_generation_ready.user_channel_id);
704 assert(!memcmp(&event_id, &user_id_1, 16));
705 assert(queue.events[0]->funding_generation_ready.channel_value_satoshis == 40000);
706 assert(queue.events[0]->funding_generation_ready.output_script.datalen == 34);
708 assert(!memcmp(queue.events[0]->funding_generation_ready.output_script.data, channel_open_block + 58 + 81, 34));
709 LDKTransaction funding_transaction { .data = const_cast<uint8_t*>(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false };
711 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);
712 assert(fund_res->result_ok);
715 std::this_thread::yield();
717 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received FundingGenerationReady event!" << std::endl;
719 // We observe when the funding signed messages have been exchanged by
720 // waiting for two monitors to be registered.
721 assert(num_txs_broadcasted == 0);
722 PeerManager_process_events(&net1);
723 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting transaction broadcast..." << std::endl;
724 while (num_txs_broadcasted != 1) {
725 std::this_thread::yield();
727 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Transaction was broadcast!" << std::endl;
729 // Note that the channel ID is the same as the channel txid reversed as the output index is 0
730 uint8_t expected_chan_id[32];
731 for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
733 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
736 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
737 ev1.process_pending_events(handler);
738 if (queue.events.size() == 1) {
739 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
740 assert(!memcmp(queue.events[0]->channel_pending.channel_id.data, expected_chan_id, 32));
743 std::this_thread::yield();
745 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
747 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
748 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelPending event..." << std::endl;
751 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
752 ev2.process_pending_events(handler);
753 if (queue.events.size() == 1) {
754 assert(queue.events[0]->tag == LDKEvent_ChannelPending);
755 assert(!memcmp(queue.events[0]->channel_pending.channel_id.data, expected_chan_id, 32));
758 std::this_thread::yield();
760 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelPending event!" << std::endl;
762 LDK::Listen listener1 = ChannelManager_as_Listen(&cm1);
763 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
765 LDK::Listen listener2 = ChannelManager_as_Listen(&cm2);
766 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
768 LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
769 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
770 mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
772 txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
773 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
774 mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
776 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
777 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
778 mons1.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
779 mons2.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
781 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
782 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
783 mons1.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
784 mons2.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
786 PeerManager_process_events(&net1);
787 PeerManager_process_events(&net2);
789 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
792 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
793 ev2.process_pending_events(handler);
794 if (queue.events.size() == 1) {
795 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
796 assert(!memcmp(queue.events[0]->channel_ready.channel_id.data, expected_chan_id, 32));
799 std::this_thread::yield();
801 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
803 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting ChannelReady event..." << std::endl;
806 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
807 ev1.process_pending_events(handler);
808 if (queue.events.size() == 1) {
809 assert(queue.events[0]->tag == LDKEvent_ChannelReady);
810 assert(!memcmp(queue.events[0]->channel_ready.channel_id.data, expected_chan_id, 32));
813 std::this_thread::yield();
815 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received ChannelReady event!" << std::endl;
817 // Now send funds from 1 to 2!
818 uint64_t channel_scid;
819 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
821 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
822 if (outbound_channels->datalen == 1) {
823 const LDKChannelDetails *channel = &outbound_channels->data[0];
824 LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
826 assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
828 ChannelCounterparty_get_node_id(&counterparty).compressed_form,
829 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
830 assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
831 // We opened the channel with 1000 push_msat:
832 assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
833 40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
834 int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
835 if (inbound_capacity < 0) inbound_capacity = 0;
836 assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
837 assert(ChannelDetails_get_is_usable(channel));
838 LDK::COption_u64Z scid_opt = ChannelDetails_get_short_channel_id(channel);
839 assert(scid_opt->some);
840 channel_scid = scid_opt->some;
843 std::this_thread::yield();
845 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
847 LDKCOption_u64Z min_value = {
848 .tag = LDKCOption_u64Z_Some,
851 LDK::CResult_Bolt11InvoiceSignOrCreationErrorZ invoice = create_invoice_from_channelmanager(&cm2,
852 KeysManager_as_NodeSigner(&keys2), logger2,
853 LDKCurrency_Bitcoin, min_value,
855 .chars = (const uint8_t *)"Invoice Description",
856 .len = strlen("Invoice Description"),
857 .chars_is_owned = false
858 }, 3600, COption_u16Z_none());
859 assert(invoice->result_ok);
860 LDKThirtyTwoBytes payment_hash;
861 memcpy(payment_hash.data, Bolt11Invoice_payment_hash(invoice->contents.result), 32);
864 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
865 LDK::ScoreLookUp chan_scorer = LDKScoreLookUp {
866 .this_arg = NULL, .channel_penalty_msat = get_chan_score, .free = NULL,
868 LDK::Payee payee = Payee_clear(ChannelManager_get_our_node_id(&cm2), Bolt11Invoice_route_hints(invoice->contents.result),
869 LDKBolt11InvoiceFeatures {
870 .inner = NULL, .is_owned = false
871 }, Bolt11Invoice_min_final_cltv_expiry_delta(invoice->contents.result));
872 LDK::RouteParameters route_params = RouteParameters_from_payment_params_and_value(
873 PaymentParameters_new(std::move(payee), COption_u64Z_none(), 0xffffffff, 1, 2,
874 LDKCVec_u64Z { .data = NULL, .datalen = 0 }, LDKCVec_u64Z { .data = NULL, .datalen = 0 }),
876 random_bytes = entropy_source1.get_secure_random_bytes();
877 LDK::ProbabilisticScoringFeeParameters params = ProbabilisticScoringFeeParameters_default();
879 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);
881 assert(route->result_ok);
882 LDK::CVec_PathZ paths = Route_get_paths(route->contents.result);
883 assert(paths->datalen == 1);
884 LDK::CVec_RouteHopZ hops = Path_get_hops(&paths->data[0]);
885 assert(hops->datalen == 1);
886 assert(!memcmp(RouteHop_get_pubkey(&hops->data[0]).compressed_form,
887 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
888 assert(RouteHop_get_short_channel_id(&hops->data[0]) == channel_scid);
889 LDKThirtyTwoBytes payment_secret;
890 memcpy(payment_secret.data, Bolt11Invoice_payment_secret(invoice->contents.result), 32);
891 LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment_with_route(&cm1,
892 route->contents.result, payment_hash, RecipientOnionFields_secret_only(payment_secret), payment_hash);
893 assert(send_res->result_ok);
897 PeerManager_process_events(&net1);
898 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 4 updated monitors..." << std::endl;
899 while (mons_updated != 4) {
900 std::this_thread::yield();
902 std::cout << __FILE__ << ":" << __LINE__ << " - " << "4 monitors updated!" << std::endl;
904 // Check that we received the payment!
905 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
908 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
909 ev2.process_pending_events(handler);
910 if (queue.events.size() == 1) {
911 assert(queue.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
914 std::this_thread::yield();
916 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
917 ChannelManager_process_pending_htlc_forwards(&cm2);
918 PeerManager_process_events(&net2);
921 LDKThirtyTwoBytes payment_preimage;
924 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
925 ev2.process_pending_events(handler);
926 assert(queue.events.size() == 1);
927 assert(queue.events[0]->tag == LDKEvent_PaymentClaimable);
928 assert(!memcmp(queue.events[0]->payment_claimable.payment_hash.data, payment_hash.data, 32));
929 assert(queue.events[0]->payment_claimable.purpose.tag == LDKPaymentPurpose_InvoicePayment);
930 assert(!memcmp(queue.events[0]->payment_claimable.purpose.invoice_payment.payment_secret.data,
931 Bolt11Invoice_payment_secret(invoice->contents.result), 32));
932 assert(queue.events[0]->payment_claimable.amount_msat == 5000);
933 assert(queue.events[0]->payment_claimable.purpose.invoice_payment.payment_preimage.tag == LDKCOption_ThirtyTwoBytesZ_Some);
934 memcpy(payment_preimage.data, queue.events[0]->payment_claimable.purpose.invoice_payment.payment_preimage.some.data, 32);
935 ChannelManager_claim_funds(&cm2, payment_preimage);
937 queue.events.clear();
938 ev2.process_pending_events(handler);
939 assert(queue.events.size() == 1);
940 assert(queue.events[0]->tag == LDKEvent_PaymentClaimed);
941 assert(!memcmp(queue.events[0]->payment_claimed.payment_hash.data, payment_hash.data, 32));
942 assert(queue.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_InvoicePayment);
944 PeerManager_process_events(&net2);
945 // Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
948 LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
949 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
950 while (queue.events.size() < 2) {
951 ev1.process_pending_events(handler);
952 std::this_thread::yield();
954 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
955 assert(queue.events.size() == 2);
956 assert(queue.events[0]->tag == LDKEvent_PaymentSent);
957 assert(!memcmp(queue.events[0]->payment_sent.payment_preimage.data, payment_preimage.data, 32));
958 assert(queue.events[1]->tag == LDKEvent_PaymentPathSuccessful);
959 assert(queue.events[1]->payment_path_successful.payment_hash.tag == LDKCOption_ThirtyTwoBytesZ_Some);
960 assert(!memcmp(queue.events[1]->payment_path_successful.payment_hash.some.data, payment_hash.data, 32));
962 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 5 updated monitors..." << std::endl;
963 while (mons_updated != 5) {
964 std::this_thread::yield();
966 std::cout << __FILE__ << ":" << __LINE__ << " - " << "5 monitors updated!" << std::endl;
970 cm1_ser = ChannelManager_write(&cm1);
971 cm2_ser = ChannelManager_write(&cm2);
974 LDK::CVec_ChannelMonitorZ mons_list1 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
975 assert(mons1.mons.size() == 1);
976 mons_list1->data[0] = *& std::get<1>(mons1.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
977 mons_list1->data[0].is_owned = false; // XXX: God this sucks
978 uint8_t node_seed[32];
979 memset(&node_seed, 0, 32);
980 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 1, 0);
981 LDK::NodeSigner node_signer1 = KeysManager_as_NodeSigner(&keys1);
982 LDK::EntropySource entropy_source1 = KeysManager_as_EntropySource(&keys1);
983 LDK::SignerProvider signer_provider1 = KeysManager_as_SignerProvider(&keys1);
985 LDK::ProbabilisticScorer scorer1 = ProbabilisticScorer_new(ProbabilisticScoringDecayParameters_default(), &net_graph1, logger1);
986 LDK::Score scorer_trait1 = ProbabilisticScorer_as_Score(&scorer1);
987 LDK::MultiThreadedLockableScore scorer_mtx1 = MultiThreadedLockableScore_new(std::move(scorer_trait1));
988 LDK::LockableScore scorer_mtx_trait1 = MultiThreadedLockableScore_as_LockableScore(&scorer_mtx1);
989 LDK::ProbabilisticScoringFeeParameters params = ProbabilisticScoringFeeParameters_default();
990 const LDK::DefaultRouter default_router_1 = DefaultRouter_new(&net_graph1, logger1, KeysManager_as_EntropySource(&keys1), std::move(scorer_mtx_trait1), std::move(params));
991 LDKRouter router1 = {
992 .this_arg = (void*)&default_router_1,
993 .find_route = NULL, // LDK currently doesn't use this, its just a default-impl
994 .find_route_with_id = custom_find_route,
998 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));
999 LDK::CResult_C2Tuple_ThirtyTwoBytesChannelManagerZDecodeErrorZ cm1_read =
1000 C2Tuple_ThirtyTwoBytesChannelManagerZ_read(LDKu8slice { .data = cm1_ser->data, .datalen = cm1_ser -> datalen}, std::move(cm1_args));
1001 assert(cm1_read->result_ok);
1002 LDK::ChannelManager cm1(std::move(cm1_read->contents.result->b));
1004 LDKCustomOnionMessageHandler custom_onion_msg_handler1 = {
1006 .handle_custom_message = NULL, // We only create custom messages, not handle them
1007 .read_custom_message = NULL, // We only create custom messages, not handle them
1008 .release_pending_custom_messages = release_no_messages,
1011 LDK::DefaultMessageRouter mr1 = DefaultMessageRouter_new(&net_graph1, KeysManager_as_EntropySource(&keys1));
1012 LDK::IgnoringMessageHandler ignorer_1 = IgnoringMessageHandler_new();
1013 LDK::OnionMessenger om1 = OnionMessenger_new(KeysManager_as_EntropySource(&keys1), KeysManager_as_NodeSigner(&keys1), logger1, DefaultMessageRouter_as_MessageRouter(&mr1), IgnoringMessageHandler_as_OffersMessageHandler(&ignorer_1), std::move(custom_onion_msg_handler1));
1015 LDK::CVec_ChannelMonitorZ mons_list2 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
1016 assert(mons2.mons.size() == 1);
1017 mons_list2->data[0] = *& std::get<1>(mons2.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
1018 mons_list2->data[0].is_owned = false; // XXX: God this sucks
1019 memset(&node_seed, 1, 32);
1020 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 1, 0);
1021 LDK::NodeSigner node_signer2 = KeysManager_as_NodeSigner(&keys2);
1022 LDK::EntropySource entropy_source2 = KeysManager_as_EntropySource(&keys2);
1023 LDK::SignerProvider signer_provider2 = KeysManager_as_SignerProvider(&keys2);
1025 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));
1026 LDK::CResult_C2Tuple_ThirtyTwoBytesChannelManagerZDecodeErrorZ cm2_read =
1027 C2Tuple_ThirtyTwoBytesChannelManagerZ_read(LDKu8slice { .data = cm2_ser->data, .datalen = cm2_ser -> datalen}, std::move(cm2_args));
1028 assert(cm2_read->result_ok);
1029 LDK::ChannelManager cm2(std::move(cm2_read->contents.result->b));
1031 CustomOnionMsgQueue peer_2_custom_onion_messages;
1032 LDKCustomOnionMessageHandler custom_onion_msg_handler2 = {
1033 .this_arg = &peer_2_custom_onion_messages,
1034 .handle_custom_message = handle_custom_onion_message,
1035 .read_custom_message = read_custom_onion_message,
1036 .release_pending_custom_messages = release_no_messages,
1039 LDK::DefaultMessageRouter mr2 = DefaultMessageRouter_new(&net_graph2, KeysManager_as_EntropySource(&keys2));
1040 LDK::IgnoringMessageHandler ignorer_2 = IgnoringMessageHandler_new();
1041 LDK::OnionMessenger om2 = OnionMessenger_new(KeysManager_as_EntropySource(&keys2), KeysManager_as_NodeSigner(&keys2), logger2, DefaultMessageRouter_as_MessageRouter(&mr2), IgnoringMessageHandler_as_OffersMessageHandler(&ignorer_2), custom_onion_msg_handler2);
1043 // Attempt to close the channel...
1044 uint8_t chan_id[32];
1045 for (int i = 0; i < 32; i++) { chan_id[i] = channel_open_txid[31-i]; }
1046 LDK::CResult_NoneAPIErrorZ close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1047 assert(!close_res->result_ok); // Note that we can't close while disconnected!
1049 // Open a connection!
1050 LDKPublicKey chan_2_node_id = ChannelManager_get_our_node_id(&cm2);
1051 LDKCustomMessageHandler custom_msg_handler1 = {
1052 .this_arg = &chan_2_node_id,
1053 .handle_custom_message = NULL, // We only create custom messages, not handle them
1054 .get_and_clear_pending_msg = create_custom_msg,
1055 .provided_node_features = custom_node_features,
1056 .provided_init_features = custom_init_features,
1057 .CustomMessageReader = LDKCustomMessageReader {
1059 .read = read_custom_message,
1064 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler1), OnionMessenger_as_OnionMessageHandler(&om1), custom_msg_handler1);
1065 random_bytes = entropy_source1.get_secure_random_bytes();
1066 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), 0xdeadbeef, &random_bytes.data, logger1, std::move(node_signer1));
1068 CustomMsgQueue peer_2_custom_messages;
1069 LDKCustomMessageHandler custom_msg_handler2 = {
1070 .this_arg = &peer_2_custom_messages,
1071 .handle_custom_message = handle_custom_message,
1072 .get_and_clear_pending_msg = never_send_custom_msgs,
1073 .provided_node_features = custom_node_features,
1074 .provided_init_features = custom_init_features,
1075 .CustomMessageReader = LDKCustomMessageReader {
1077 .read = read_custom_message,
1082 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), P2PGossipSync_as_RoutingMessageHandler(&graph_msg_handler2), OnionMessenger_as_OnionMessageHandler(&om2), custom_msg_handler2);
1083 random_bytes = entropy_source1.get_secure_random_bytes();
1084 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), 0xdeadbeef, &random_bytes.data, logger2, std::move(node_signer2));
1086 PeersConnection conn(cm1, cm2, net1, net2);
1088 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting usable channel..." << std::endl;
1090 // Wait for the channels to be considered up once the reestablish messages are processed
1091 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
1092 if (outbound_channels->datalen == 1) {
1095 std::this_thread::yield();
1097 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Listed usable channel!" << std::endl;
1099 // Send another payment, this time via the retires path
1100 LDK::CResult_Bolt11InvoiceSignOrCreationErrorZ invoice_res2 = create_invoice_from_channelmanager(&cm2,
1101 KeysManager_as_NodeSigner(&keys2), logger1,
1102 LDKCurrency_Bitcoin, COption_u64Z_some(10000),
1104 .chars = (const uint8_t *)"Invoice 2 Description",
1105 .len = strlen("Invoice 2 Description"),
1106 .chars_is_owned = false
1107 }, 3600, COption_u16Z_none());
1108 assert(invoice_res2->result_ok);
1109 const LDKBolt11Invoice *invoice2 = invoice_res2->contents.result;
1110 LDK::CResult_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ pay_params =
1111 payment_parameters_from_invoice(invoice2);
1112 LDK::RecipientOnionFields invoice2_recipient(std::move(pay_params->contents.result->b));
1113 LDK::RouteParameters invoice2_params(std::move(pay_params->contents.result->c));
1114 assert(pay_params->result_ok);
1115 LDKThirtyTwoBytes payment_id { .data = 0 };
1116 LDK::CResult_NoneRetryableSendFailureZ invoice_pay_res = ChannelManager_send_payment(
1117 &cm1, std::move(pay_params->contents.result->a), std::move(invoice2_recipient),
1118 std::move(payment_id), std::move(invoice2_params), Retry_attempts(0)
1120 assert(invoice_pay_res->result_ok);
1121 PeerManager_process_events(&net1);
1123 // Check that we received the payment!
1124 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PendingHTLCsForwardable event..." << std::endl;
1127 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1128 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1129 ev2.process_pending_events(handler2);
1130 if (queue2.events.size() == 1) {
1131 assert(queue2.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
1134 std::this_thread::yield();
1136 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PendingHTLCsForwardable event!" << std::endl;
1137 ChannelManager_process_pending_htlc_forwards(&cm2);
1138 PeerManager_process_events(&net2);
1140 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentClaimable/PaymentClaimed event..." << std::endl;
1143 LDKEventHandler handler2 = { .this_arg = &queue2, .handle_event = handle_event, .free = NULL };
1144 LDK::EventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
1145 ev2.process_pending_events(handler2);
1146 if (queue2.events.size() == 1) {
1147 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimable);
1148 const struct LDKEvent_LDKPaymentClaimable_Body *event_data = &queue2.events[0]->payment_claimable;
1149 assert(!memcmp(event_data->payment_hash.data, Bolt11Invoice_payment_hash(invoice2), 32));
1150 assert(event_data->purpose.tag == LDKPaymentPurpose_InvoicePayment);
1151 assert(!memcmp(event_data->purpose.invoice_payment.payment_secret.data,
1152 Bolt11Invoice_payment_secret(invoice2), 32));
1153 assert(event_data->amount_msat == 10000);
1154 assert(event_data->purpose.invoice_payment.payment_preimage.tag == LDKCOption_ThirtyTwoBytesZ_Some);
1155 ChannelManager_claim_funds(&cm2, event_data->purpose.invoice_payment.payment_preimage.some);
1157 queue2.events.clear();
1158 ev2.process_pending_events(handler2);
1159 assert(queue2.events.size() == 1);
1160 assert(queue2.events[0]->tag == LDKEvent_PaymentClaimed);
1161 assert(!memcmp(queue2.events[0]->payment_claimed.payment_hash.data, Bolt11Invoice_payment_hash(invoice2), 32));
1162 assert(queue2.events[0]->payment_claimed.purpose.tag == LDKPaymentPurpose_InvoicePayment);
1166 std::this_thread::yield();
1168 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentClaimable/PaymentClaimed event!" << std::endl;
1171 LDKEventHandler handler1 = { .this_arg = &queue1, .handle_event = handle_event, .free = NULL };
1172 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting PaymentSent and PaymentPathSuccessful events..." << std::endl;
1173 while (queue1.events.size() < 2) {
1174 PeerManager_process_events(&net2);
1175 PeerManager_process_events(&net1);
1177 LDK::EventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
1178 ev1.process_pending_events(handler1);
1179 std::this_thread::yield();
1181 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received PaymentSent and PaymentPathSuccessful events (presumably)!" << std::endl;
1182 assert(queue1.events.size() == 2);
1183 assert(queue1.events[0]->tag == LDKEvent_PaymentSent);
1184 assert(queue1.events[1]->tag == LDKEvent_PaymentPathSuccessful);
1186 // Actually close the channel
1187 num_txs_broadcasted = 0;
1188 close_res = ChannelManager_close_channel(&cm1, &chan_id, ChannelManager_get_our_node_id(&cm2));
1189 assert(close_res->result_ok);
1190 PeerManager_process_events(&net1);
1191 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting 2 transaction broadcasts..." << std::endl;
1192 while (num_txs_broadcasted != 2) {
1193 std::this_thread::yield();
1195 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Broadcast 2 transactions!" << std::endl;
1196 LDK::CVec_ChannelDetailsZ chans_after_close1 = ChannelManager_list_channels(&cm1);
1197 assert(chans_after_close1->datalen == 0);
1198 LDK::CVec_ChannelDetailsZ chans_after_close2 = ChannelManager_list_channels(&cm2);
1199 assert(chans_after_close2->datalen == 0);
1201 LDK::CResult_SendSuccessSendErrorZ om_send_res =
1202 OnionMessenger_send_onion_message(&om1,
1203 build_custom_onion_message(),
1204 Destination_node(ChannelManager_get_our_node_id(&cm2)),
1205 LDKBlindedPath { .inner = NULL, .is_owned = true });
1206 assert(om_send_res->result_ok);
1207 PeerManager_process_events(&net1);
1208 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Awaiting onion message..." << std::endl;
1210 std::this_thread::yield();
1211 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1212 if (peer_2_custom_onion_messages.msgs.size() != 0) break;
1214 std::cout << __FILE__ << ":" << __LINE__ << " - " << "Received onion message!" << std::endl;
1218 std::unique_lock<std::mutex> lck(peer_2_custom_onion_messages.mtx);
1219 assert(peer_2_custom_onion_messages.msgs.size() == 1);
1220 assert(peer_2_custom_onion_messages.msgs[0].tlv_type() == 8888);
1221 assert(peer_2_custom_messages.msgs.size() != 0);
1223 // Few extra random tests:
1225 memset(&sk, 42, 32);
1226 LDKThirtyTwoBytes kdiv_params;
1227 memset(&kdiv_params, 43, 32);
1228 LDK::InMemorySigner signer = InMemorySigner_new(sk, sk, sk, sk, sk, random_bytes, 42, kdiv_params, kdiv_params);