Merge pull request #46 from TheBlueMatt/main
[ldk-c-bindings] / lightning-c-bindings / demo.cpp
1 extern "C" {
2 #include <lightning.h>
3
4 #ifdef REAL_NET
5 #include <ldk_net.h>
6 #endif
7 }
8 #include "include/lightningpp.hpp"
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <unistd.h>
16
17 #include <atomic>
18 #include <chrono>
19 #include <functional>
20 #include <thread>
21 #include <mutex>
22 #include <vector>
23
24 const uint8_t valid_node_announcement[] = {
25         0x94, 0xe4, 0xf5, 0x61, 0x41, 0x24, 0x7d, 0x90, 0x23, 0xa0, 0xc8, 0x34, 0x8c, 0xc4, 0xca, 0x51,
26         0xd8, 0x17, 0x59, 0xff, 0x7d, 0xac, 0x8c, 0x9b, 0x63, 0x29, 0x1c, 0xe6, 0x12, 0x12, 0x93, 0xbd,
27         0x66, 0x4d, 0x6b, 0x9c, 0xfb, 0x35, 0xda, 0x16, 0x06, 0x3d, 0xf0, 0x8f, 0x8a, 0x39, 0x99, 0xa2,
28         0xf2, 0x5d, 0x12, 0x0f, 0x2b, 0x42, 0x1b, 0x8b, 0x9a, 0xfe, 0x33, 0x0c, 0xeb, 0x33, 0x5e, 0x52,
29         0xee, 0x99, 0xa1, 0x07, 0x06, 0xed, 0xf8, 0x48, 0x7a, 0xc6, 0xe5, 0xf5, 0x5e, 0x01, 0x3a, 0x41,
30         0x2f, 0x18, 0x94, 0x8a, 0x3b, 0x0a, 0x52, 0x3f, 0xbf, 0x61, 0xa9, 0xc5, 0x4f, 0x70, 0xee, 0xb8,
31         0x79, 0x23, 0xbb, 0x1a, 0x44, 0x7d, 0x91, 0xe6, 0x2a, 0xbc, 0xa1, 0x07, 0xbc, 0x65, 0x3b, 0x02,
32         0xd9, 0x1d, 0xb2, 0xf2, 0x3a, 0xcb, 0x75, 0x79, 0xc6, 0x66, 0xd8, 0xc1, 0x71, 0x29, 0xdf, 0x04,
33         0x60, 0xf4, 0xbf, 0x07, 0x7b, 0xb9, 0xc2, 0x11, 0x94, 0x6a, 0x28, 0xc2, 0xdd, 0xd8, 0x7b, 0x44,
34         0x8f, 0x08, 0xe3, 0xc8, 0xd8, 0xf4, 0x81, 0xb0, 0x9f, 0x94, 0xcb, 0xc8, 0xc1, 0x3c, 0xc2, 0x6e,
35         0x31, 0x26, 0xfc, 0x33, 0x16, 0x3b, 0xe0, 0xde, 0xa1, 0x16, 0x21, 0x9f, 0x89, 0xdd, 0x97, 0xa4,
36         0x41, 0xf2, 0x9f, 0x19, 0xb1, 0xae, 0x82, 0xf7, 0x85, 0x9a, 0xb7, 0x8f, 0xb7, 0x52, 0x7a, 0x72,
37         0xf1, 0x5e, 0x89, 0xe1, 0x8a, 0xcd, 0x40, 0xb5, 0x8e, 0xc3, 0xca, 0x42, 0x76, 0xa3, 0x6e, 0x1b,
38         0xf4, 0x87, 0x35, 0x30, 0x58, 0x43, 0x04, 0xd9, 0x2c, 0x50, 0x54, 0x55, 0x47, 0x6f, 0x70, 0x9b,
39         0x42, 0x1f, 0x91, 0xfc, 0xa1, 0xdb, 0x72, 0x53, 0x96, 0xc8, 0xe5, 0xcd, 0x0e, 0xcb, 0xa0, 0xfe,
40         0x6b, 0x08, 0x77, 0x48, 0xb7, 0xad, 0x4a, 0x69, 0x7c, 0xdc, 0xd8, 0x04, 0x28, 0x35, 0x9b, 0x73,
41         0x00, 0x00, 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce,
42         0xc3, 0xae, 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, 0x01, 0xea, 0x33, 0x09, 0x00, 0x00,
43         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5b, 0xe5, 0xe9, 0x47, 0x82,
44         0x09, 0x67, 0x4a, 0x96, 0xe6, 0x0f, 0x1f, 0x03, 0x7f, 0x61, 0x76, 0x54, 0x0f, 0xd0, 0x01, 0xfa,
45         0x1d, 0x64, 0x69, 0x47, 0x70, 0xc5, 0x6a, 0x77, 0x09, 0xc4, 0x2c, 0x03, 0x5c, 0x4e, 0x0d, 0xec,
46         0x72, 0x15, 0xe2, 0x68, 0x33, 0x93, 0x87, 0x30, 0xe5, 0xe5, 0x05, 0xaa, 0x62, 0x50, 0x4d, 0xa8,
47         0x5b, 0xa5, 0x71, 0x06, 0xa4, 0x6b, 0x5a, 0x24, 0x04, 0xfc, 0x9d, 0x8e, 0x02, 0xba, 0x72, 0xa6,
48         0xe8, 0xba, 0x53, 0xe8, 0xb9, 0x71, 0xad, 0x0c, 0x98, 0x23, 0x96, 0x8a, 0xef, 0x4d, 0x78, 0xce,
49         0x8a, 0xf2, 0x55, 0xab, 0x43, 0xdf, 0xf8, 0x30, 0x03, 0xc9, 0x02, 0xfb, 0x8d, 0x02, 0x16, 0x34,
50         0x5b, 0xf8, 0x31, 0x16, 0x4a, 0x03, 0x75, 0x8e, 0xae, 0xa5, 0xe8, 0xb6, 0x6f, 0xee, 0x2b, 0xe7,
51         0x71, 0x0b, 0x8f, 0x19, 0x0e, 0xe8, 0x80, 0x24, 0x90, 0x32, 0xa2, 0x9e, 0xd6, 0x6e
52 };
53
54 // A simple block containing only one transaction (which is the channel-open transaction for the
55 // channel we'll create). This was originally created by printing additional data in a simple
56 // rust-lightning unit test.
57 const uint8_t channel_open_block[] = {
58         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60         0x00, 0x00, 0x00, 0x00, 0xa2, 0x47, 0xd2, 0xf8, 0xd4, 0xe0, 0x6a, 0x3f, 0xf9, 0x7a, 0x9a, 0x34,
61         0xbb, 0xa9, 0x96, 0xde, 0x63, 0x84, 0x5a, 0xce, 0xcf, 0x98, 0xb8, 0xbb, 0x75, 0x4c, 0x4f, 0x7d,
62         0xee, 0x4c, 0xa9, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63         0x01, // transaction count
64         0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67         0x01, 0x40, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0xd1, 0xd9, 0x13, 0xa9,
68         0x76, 0x09, 0x05, 0xa3, 0x4d, 0x13, 0x5b, 0x69, 0xaa, 0xe7, 0x79, 0x71, 0xb9, 0x75, 0xa1, 0xd0,
69         0x77, 0xcb, 0xa2, 0xf6, 0x6a, 0x25, 0x37, 0x3a, 0xaf, 0xdc, 0x11, 0x09, 0x01, 0x00, 0x00, 0x00,
70         0x00, 0x00
71 };
72
73 // The first transaction in the block is header (80 bytes) + transaction count (1 byte) into the block data.
74 const uint8_t channel_open_txid[] = {
75         0x02, 0xe0, 0x50, 0x05, 0x33, 0xd3, 0x29, 0x66, 0x0c, 0xb2, 0xcb, 0x1e, 0x7a, 0x4a, 0xc7, 0xc7,
76         0x8b, 0x02, 0x46, 0x7e, 0x30, 0x2c, 0xe6, 0x19, 0xce, 0x43, 0x3e, 0xdf, 0x43, 0x65, 0xae, 0xf9,
77 };
78
79 // Two blocks built on top of channel_open_block:
80 const uint8_t block_1[81] = {
81         0x01, 0x00, 0x00, 0x00, 0x0c, 0x7a, 0xc2, 0xdc, 0x08, 0xaf, 0x40, 0x7d, 0x58, 0x81, 0x9b, 0x44,
82         0xc7, 0xe0, 0x0f, 0x78, 0xc0, 0xd1, 0x01, 0xa2, 0x03, 0x16, 0x4a, 0x8d, 0x92, 0x66, 0x4e, 0xaf,
83         0x7f, 0xfc, 0x6e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86         0x00, // transaction count
87 };
88 const uint8_t block_2[81] = {
89         0x01, 0x00, 0x00, 0x00, 0x36, 0x0b, 0xf5, 0x46, 0x4a, 0xc7, 0x26, 0x4c, 0x4b, 0x36, 0xa6, 0x9d,
90         0x0e, 0xf0, 0x14, 0xfb, 0x8a, 0xcb, 0x20, 0x84, 0x18, 0xf3, 0xaa, 0x77, 0x32, 0x2d, 0xf7, 0x48,
91         0x62, 0x92, 0xb1, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94         0x00, // transaction count
95 };
96
97 const LDKThirtyTwoBytes genesis_hash = { // We don't care particularly if this is "right"
98         .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 }
99 };
100
101 void print_log(const void *this_arg, const char *record) {
102         printf("%p - %s\n", this_arg, record);
103 }
104
105 uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) {
106         if (target == LDKConfirmationTarget_Background) {
107                 return 253;
108         } else {
109                 return 507;
110         }
111         // Note that we don't call _free() on target, but that's OK, its unitary
112 }
113 // We use the same fee estimator globally:
114 const LDKFeeEstimator fee_est {
115         .this_arg = NULL,
116         .get_est_sat_per_1000_weight = get_fee,
117         .free = NULL,
118 };
119
120 static std::atomic_int num_txs_broadcasted(0);
121 void broadcast_tx(const void *this_arg, LDKTransaction tx) {
122         num_txs_broadcasted += 1;
123         //TODO
124         Transaction_free(tx);
125 }
126
127 struct NodeMonitors {
128         std::mutex mut;
129         std::vector<std::pair<LDK::OutPoint, LDK::ChannelMonitor>> mons;
130         LDKLogger* logger;
131
132         void ConnectBlock(const uint8_t (*header)[80], uint32_t height, LDKCVec_C2Tuple_usizeTransactionZZ tx_data, LDKBroadcasterInterface broadcast, LDKFeeEstimator fee_est) {
133                 std::unique_lock<std::mutex> l(mut);
134                 for (auto& mon : mons) {
135                         LDK::CVec_TransactionOutputsZ res = ChannelMonitor_block_connected(&mon.second, header, tx_data, height, broadcast, fee_est, *logger);
136                 }
137         }
138 };
139
140 LDKCResult_NoneChannelMonitorUpdateErrZ add_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, LDKChannelMonitor monitor_arg) {
141         // First bind the args to C++ objects so they auto-free
142         LDK::ChannelMonitor mon(std::move(monitor_arg));
143         LDK::OutPoint funding_txo(std::move(funding_txo_arg));
144
145         NodeMonitors* arg = (NodeMonitors*) this_arg;
146         std::unique_lock<std::mutex> l(arg->mut);
147
148         arg->mons.push_back(std::make_pair(std::move(funding_txo), std::move(mon)));
149         return CResult_NoneChannelMonitorUpdateErrZ_ok();
150 }
151 static std::atomic_int mons_updated(0);
152 LDKCResult_NoneChannelMonitorUpdateErrZ update_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, LDKChannelMonitorUpdate monitor_arg) {
153         // First bind the args to C++ objects so they auto-free
154         LDK::ChannelMonitorUpdate update(std::move(monitor_arg));
155         LDK::OutPoint funding_txo(std::move(funding_txo_arg));
156
157         NodeMonitors* arg = (NodeMonitors*) this_arg;
158         std::unique_lock<std::mutex> l(arg->mut);
159
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)) {
164                         updated = true;
165                         LDKBroadcasterInterface broadcaster = {
166                                 .broadcast_transaction = broadcast_tx,
167                         };
168                         LDK::CResult_NoneMonitorUpdateErrorZ res = ChannelMonitor_update_monitor(&mon.second, &update, &broadcaster, &fee_est, arg->logger);
169                         assert(res->result_ok);
170                 }
171         }
172         assert(updated);
173
174         mons_updated += 1;
175         return CResult_NoneChannelMonitorUpdateErrZ_ok();
176 }
177 LDKCVec_MonitorEventZ monitors_pending_monitor_events(const void *this_arg) {
178         NodeMonitors* arg = (NodeMonitors*) this_arg;
179         std::unique_lock<std::mutex> l(arg->mut);
180
181         if (arg->mons.size() == 0) {
182                 return LDKCVec_MonitorEventZ {
183                         .data = NULL,
184                         .datalen = 0,
185                 };
186         } else {
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                 return ChannelMonitor_get_and_clear_pending_monitor_events(&arg->mons[0].second);
191         }
192 }
193
194 struct EventQueue {
195         std::vector<LDK::Event> events;
196 };
197 void handle_event(const void *this_arg, const LDKEvent *event) {
198         EventQueue* arg = (EventQueue*) this_arg;
199         arg->events.push_back(Event_clone(event));
200 }
201
202 #ifdef REAL_NET
203 class PeersConnection {
204         void* node1_handler;
205         void* node2_handler;
206
207 public:
208         PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
209                 node1_handler = init_socket_handling(&net1);
210                 node2_handler = init_socket_handling(&net2);
211
212                 struct sockaddr_in listen_addr;
213                 listen_addr.sin_family = AF_INET;
214                 listen_addr.sin_addr.s_addr = htonl((127 << 8*3) | 1);
215                 listen_addr.sin_port = htons(10042);
216                 assert(!socket_bind(node2_handler, (sockaddr*)&listen_addr, sizeof(listen_addr)));
217
218                 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
219
220                 while (true) {
221                         // Wait for the initial handshakes to complete...
222                         LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
223                         LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
224                         if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
225                         std::this_thread::yield();
226                 }
227
228                 // Connect twice, which should auto-disconnect, and is a good test of our disconnect pipeline
229                 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
230                 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
231
232                 // Then disconnect the "main" connection, while another connection is being made.
233                 PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
234                 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
235
236                 // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
237                 while (true) {
238                         PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
239                         // Wait for the peers to disconnect...
240                         LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
241                         LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
242                         if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
243                         std::this_thread::yield();
244                 }
245                 // Note that the above is somewhat race-y, as node 2 may still think its connected.
246                 // Thus, make sure any connections are disconnected on its end as well.
247                 PeerManager_disconnect_by_node_id(&net2, ChannelManager_get_our_node_id(&cm1), false);
248
249                 // Finally make an actual connection and keep it this time
250                 assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
251
252                 while (true) {
253                         // Wait for the initial handshakes to complete...
254                         LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
255                         LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
256                         if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
257                         std::this_thread::yield();
258                 }
259         }
260         void stop() {
261                 interrupt_socket_handling(node1_handler);
262                 interrupt_socket_handling(node2_handler);
263         }
264 };
265
266 #else // REAL_NET
267
268 uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
269         return write((int)((long)this_arg), data.data, data.datalen);
270 }
271 void sock_disconnect_socket(void *this_arg) {
272         close((int)((long)this_arg));
273 }
274 bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) {
275         return this_arg == other_arg->this_arg;
276 }
277 uint64_t sock_hash(const void *this_arg) {
278         return (uint64_t)this_arg;
279 }
280 void sock_read_data_thread(int rdfd, LDKSocketDescriptor *peer_descriptor, LDKPeerManager *pm) {
281         unsigned char buf[1024];
282         LDKu8slice data;
283         data.data = buf;
284         ssize_t readlen = 0;
285         while ((readlen = read(rdfd, buf, 1024)) > 0) {
286                 data.datalen = readlen;
287                 LDK::CResult_boolPeerHandleErrorZ res = PeerManager_read_event(&*pm, peer_descriptor, data);
288                 if (!res->result_ok) {
289                         peer_descriptor->disconnect_socket(peer_descriptor->this_arg);
290                         return;
291                 }
292                 PeerManager_process_events(pm);
293         }
294         PeerManager_socket_disconnected(&*pm, peer_descriptor);
295 }
296
297 class PeersConnection {
298         int pipefds_1_to_2[2];
299         int pipefds_2_to_1[2];
300         std::thread t1, t2;
301         LDKSocketDescriptor sock1, sock2;
302
303 public:
304         PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
305                 assert(!pipe(pipefds_1_to_2));
306                 assert(!pipe(pipefds_2_to_1));
307
308                 sock1 = LDKSocketDescriptor {
309                         .this_arg = (void*)(long)pipefds_1_to_2[1],
310                         .send_data = sock_send_data,
311                         .disconnect_socket = sock_disconnect_socket,
312                         .eq = sock_eq,
313                         .hash = sock_hash,
314                         .cloned = NULL,
315                         .free = NULL,
316                 };
317
318                 sock2 = LDKSocketDescriptor {
319                         .this_arg = (void*)(long)pipefds_2_to_1[1],
320                         .send_data = sock_send_data,
321                         .disconnect_socket = sock_disconnect_socket,
322                         .eq = sock_eq,
323                         .hash = sock_hash,
324                         .cloned = NULL,
325                         .free = NULL,
326                 };
327
328                 t1 = std::thread(&sock_read_data_thread, pipefds_2_to_1[0], &sock1, &net1);
329                 t2 = std::thread(&sock_read_data_thread, pipefds_1_to_2[0], &sock2, &net2);
330
331                 // Note that we have to bind the result to a C++ class to make sure it gets free'd
332                 LDK::CResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(&net1, ChannelManager_get_our_node_id(&cm2), sock1);
333                 assert(con_res->result_ok);
334                 LDK::CResult_NonePeerHandleErrorZ con_res2 = PeerManager_new_inbound_connection(&net2, sock2);
335                 assert(con_res2->result_ok);
336
337                 auto writelen = write(pipefds_1_to_2[1], con_res->contents.result->data, con_res->contents.result->datalen);
338                 assert(writelen > 0 && uint64_t(writelen) == con_res->contents.result->datalen);
339
340                 while (true) {
341                         // Wait for the initial handshakes to complete...
342                         LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
343                         LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
344                         if (peers_1->datalen == 1 && peers_2->datalen ==1) { break; }
345                         std::this_thread::yield();
346                 }
347         }
348
349         void stop() {
350                 close(pipefds_1_to_2[0]);
351                 close(pipefds_2_to_1[0]);
352                 close(pipefds_1_to_2[1]);
353                 close(pipefds_2_to_1[1]);
354                 t1.join();
355                 t2.join();
356         }
357 };
358 #endif // !REAL_NET
359
360 struct CustomMsgQueue {
361         std::vector<LDK::Type> msgs;
362 };
363
364 uint16_t custom_msg_type_id(const void *this_arg) {
365         return 8888;
366 }
367 LDKCVec_u8Z custom_msg_bytes(const void *this_arg) {
368         uint8_t *bytes = (uint8_t *) malloc(1024);
369         memset(bytes, 42, 1024);
370         return LDKCVec_u8Z {
371                 .data = bytes, .datalen = 1024
372         };
373 }
374 LDKStr custom_msg_debug(const void *this_arg) {
375         return LDKStr {
376                 .chars = NULL, .len = 0, .chars_is_owned = false
377         };
378 }
379
380 LDKCResult_COption_TypeZDecodeErrorZ read_custom_message(const void* this_arg, uint16_t type_id, LDKu8slice buf) {
381         assert(type_id == 8888);
382         assert(buf.datalen == 1024);
383         uint8_t cmp[1024];
384         memset(cmp, 42, 1024);
385         assert(!memcmp(cmp, buf.data, 1024));
386         return CResult_COption_TypeZDecodeErrorZ_ok(COption_TypeZ_some(LDKType {
387                 .this_arg = NULL,
388                 .type_id = custom_msg_type_id,
389                 .debug_str = custom_msg_debug,
390                 .free = NULL,
391         }));
392 }
393
394 LDKCResult_NoneLightningErrorZ handle_custom_message(const void* this_arg, struct LDKType msg, struct LDKPublicKey _sender_node_id) {
395         CustomMsgQueue* arg = (CustomMsgQueue*) this_arg;
396         arg->msgs.push_back(std::move(msg));
397         return CResult_NoneLightningErrorZ_ok();
398 }
399 LDKCVec_C2Tuple_PublicKeyTypeZZ never_send_custom_msgs(const void* this_arg) {
400         return LDKCVec_C2Tuple_PublicKeyTypeZZ {
401                 .data = NULL, .datalen = 0
402         };
403 }
404
405 LDKCVec_C2Tuple_PublicKeyTypeZZ create_custom_msg(const void* this_arg) {
406         const LDKPublicKey *counterparty_node_id = (const LDKPublicKey *)this_arg;
407         LDKCVec_C2Tuple_PublicKeyTypeZZ ret = {
408                 .data = ((LDKC2Tuple_PublicKeyTypeZ*)malloc(sizeof(LDKC2Tuple_PublicKeyTypeZ))),
409                 .datalen = 1
410         };
411         ret.data[0].a = *counterparty_node_id;
412         ret.data[0].b = LDKType {
413                 .this_arg = NULL,
414                 .type_id = custom_msg_type_id,
415                 .debug_str = custom_msg_debug,
416                 .write = custom_msg_bytes,
417                 .free = NULL,
418         };
419         return ret;
420 }
421
422 uint64_t get_chan_score(const void *this_arg, uint64_t scid) { return 42; }
423
424 int main() {
425         uint8_t channel_open_header[80];
426         uint8_t header_1[80];
427         uint8_t header_2[80];
428         memcpy(channel_open_header, channel_open_block, 80);
429         memcpy(header_1, block_1, 80);
430         memcpy(header_2, block_2, 80);
431
432         LDKPublicKey null_pk;
433         memset(&null_pk, 0, sizeof(null_pk));
434
435         LDKThirtyTwoBytes random_bytes;
436         LDKThirtyTwoBytes chain_tip;
437         memset(&chain_tip, 0, sizeof(chain_tip)); // channel_open_header's prev_blockhash is all-0s
438
439         LDKNetwork network = LDKNetwork_Testnet;
440
441         // Trait implementations:
442         LDKBroadcasterInterface broadcast {
443                 .this_arg = NULL,
444                 .broadcast_transaction = broadcast_tx,
445                 .free = NULL,
446         };
447
448         // Instantiate classes for the nodes that don't get reloaded on a ser-des reload
449         LDKLogger logger1 {
450                 .this_arg = (void*)1,
451                 .log = print_log,
452                 .free = NULL,
453         };
454
455         NodeMonitors mons1;
456         mons1.logger = &logger1;
457         LDKWatch mon1 {
458                 .this_arg = &mons1,
459                 .watch_channel = add_channel_monitor,
460                 .update_channel = update_channel_monitor,
461                 .release_pending_monitor_events = monitors_pending_monitor_events,
462                 .free = NULL,
463         };
464
465         LDK::NetGraphMsgHandler net_graph1 = NetGraphMsgHandler_new(NetworkGraph_new(genesis_hash), COption_AccessZ_none(), logger1);
466         LDKSecretKey node_secret1;
467
468         LDKLogger logger2 {
469                 .this_arg = (void*)2,
470                 .log = print_log,
471                 .free = NULL,
472         };
473
474         NodeMonitors mons2;
475         mons2.logger = &logger2;
476         LDKWatch mon2 {
477                 .this_arg = &mons2,
478                 .watch_channel = add_channel_monitor,
479                 .update_channel = update_channel_monitor,
480                 .release_pending_monitor_events = monitors_pending_monitor_events,
481                 .free = NULL,
482         };
483
484         LDK::NetGraphMsgHandler net_graph2 = NetGraphMsgHandler_new(NetworkGraph_new(genesis_hash), COption_AccessZ_none(), logger2);
485         LDKSecretKey node_secret2;
486
487         LDK::CVec_u8Z cm1_ser = LDKCVec_u8Z {}; // ChannelManager 1 serialization at the end of the ser-des scope
488         LDK::CVec_u8Z cm2_ser = LDKCVec_u8Z {}; // ChannelManager 2 serialization at the end of the ser-des scope
489
490         { // Scope for the ser-des reload
491                 // Instantiate classes for node 1:
492                 uint8_t node_seed[32];
493                 memset(&node_seed, 0, 32);
494                 LDK::KeysManager keys1 = KeysManager_new(&node_seed, 0, 0);
495                 LDK::KeysInterface keys_source1 = KeysManager_as_KeysInterface(&keys1);
496                 node_secret1 = keys_source1->get_node_secret(keys_source1->this_arg);
497
498                 LDK::ChannelManager cm1 = ChannelManager_new(fee_est, mon1, broadcast, logger1, KeysManager_as_KeysInterface(&keys1), UserConfig_default(), ChainParameters_new(network, BestBlock_new(chain_tip, 0)));
499
500                 LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
501                 assert(channels->datalen == 0);
502
503                 LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph1));
504
505                 LDK::IgnoringMessageHandler ignoring_handler1 = IgnoringMessageHandler_new();
506                 LDK::CustomMessageHandler custom_msg_handler1 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler1);
507
508                 random_bytes = keys_source1->get_secure_random_bytes(keys_source1->this_arg);
509                 LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), node_secret1, &random_bytes.data, logger1, std::move(custom_msg_handler1));
510
511                 // Demo getting a channel key and check that its returning real pubkeys:
512                 LDK::Sign chan_signer1 = keys_source1->get_channel_signer(keys_source1->this_arg, false, 42);
513                 chan_signer1->BaseSign.set_pubkeys(&chan_signer1->BaseSign); // Make sure pubkeys is defined
514                 LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->BaseSign.pubkeys);
515                 assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
516
517                 // Instantiate classes for node 2:
518                 memset(&node_seed, 1, 32);
519                 LDK::KeysManager keys2 = KeysManager_new(&node_seed, 0, 0);
520                 LDK::KeysInterface keys_source2 = KeysManager_as_KeysInterface(&keys2);
521                 node_secret2 = keys_source2->get_node_secret(keys_source2->this_arg);
522
523                 LDK::ChannelHandshakeConfig handshake_config2 = ChannelHandshakeConfig_default();
524                 ChannelHandshakeConfig_set_minimum_depth(&handshake_config2, 2);
525                 LDK::UserConfig config2 = UserConfig_default();
526                 UserConfig_set_own_channel_config(&config2, std::move(handshake_config2));
527
528                 LDK::ChannelManager cm2 = ChannelManager_new(fee_est, mon2, broadcast, logger2, KeysManager_as_KeysInterface(&keys2), std::move(config2), ChainParameters_new(network, BestBlock_new(chain_tip, 0)));
529
530                 LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
531                 assert(channels2->datalen == 0);
532
533                 LDK::RoutingMessageHandler net_msgs2 = NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph2);
534                 LDK::CResult_ChannelAnnouncementDecodeErrorZ chan_ann = ChannelAnnouncement_read(LDKu8slice { .data = valid_node_announcement, .datalen = sizeof(valid_node_announcement) });
535                 assert(chan_ann->result_ok);
536                 LDK::CResult_boolLightningErrorZ ann_res = net_msgs2->handle_channel_announcement(net_msgs2->this_arg, chan_ann->contents.result);
537                 assert(ann_res->result_ok);
538
539                 LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), std::move(net_msgs2));
540
541                 LDK::IgnoringMessageHandler ignoring_handler2 = IgnoringMessageHandler_new();
542                 LDK::CustomMessageHandler custom_msg_handler2 = IgnoringMessageHandler_as_CustomMessageHandler(&ignoring_handler2);
543
544                 random_bytes = keys_source2->get_secure_random_bytes(keys_source2->this_arg);
545                 LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), node_secret2, &random_bytes.data, logger2, std::move(custom_msg_handler2));
546
547                 // Open a connection!
548                 PeersConnection conn(cm1, cm2, net1, net2);
549
550                 // Note that we have to bind the result to a C++ class to make sure it gets free'd
551                 LDK::CResult__u832APIErrorZ res = ChannelManager_create_channel(&cm1, ChannelManager_get_our_node_id(&cm2), 40000, 1000, 42, UserConfig_default());
552                 assert(res->result_ok);
553                 PeerManager_process_events(&net1);
554
555                 LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
556                 assert(new_channels->datalen == 1);
557                 LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
558                 LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
559                 assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
560
561                 while (true) {
562                         LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
563                         if (new_channels_2->datalen == 1) {
564                                 // Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
565                                 LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
566                                 const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
567                                 assert(init_feats->inner != NULL);
568                                 break;
569                         }
570                         std::this_thread::yield();
571                 }
572
573                 LDKEventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
574                 while (true) {
575                         EventQueue queue;
576                         LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
577                         ev1.process_pending_events(ev1.this_arg, handler);
578                         if (queue.events.size() == 1) {
579                                 assert(queue.events[0]->tag == LDKEvent_FundingGenerationReady);
580                                 assert(queue.events[0]->funding_generation_ready.user_channel_id == 42);
581                                 assert(queue.events[0]->funding_generation_ready.channel_value_satoshis == 40000);
582                                 assert(queue.events[0]->funding_generation_ready.output_script.datalen == 34);
583                                 assert(!memcmp(queue.events[0]->funding_generation_ready.output_script.data, channel_open_block + 58 + 81, 34));
584                                 LDKTransaction funding_transaction { .data = const_cast<uint8_t*>(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false };
585
586                                 LDK::CResult_NoneAPIErrorZ fund_res = ChannelManager_funding_transaction_generated(&cm1, &queue.events[0]->funding_generation_ready.temporary_channel_id.data, funding_transaction);
587                                 assert(fund_res->result_ok);
588                                 break;
589                         }
590                         std::this_thread::yield();
591                 }
592
593                 // We observe when the funding signed messages have been exchanged by
594                 // waiting for two monitors to be registered.
595                 assert(num_txs_broadcasted == 0);
596                 PeerManager_process_events(&net1);
597                 while (num_txs_broadcasted != 1) {
598                         std::this_thread::yield();
599                 }
600
601                 LDK::Listen listener1 = ChannelManager_as_Listen(&cm1);
602                 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
603
604                 LDK::Listen listener2 = ChannelManager_as_Listen(&cm2);
605                 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
606
607                 LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
608                 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
609                 mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
610
611                 txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
612                 *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
613                 mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
614
615                 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
616                 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
617                 mons1.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
618                 mons2.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
619
620                 listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
621                 listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
622                 mons1.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
623                 mons2.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
624
625                 PeerManager_process_events(&net1);
626                 PeerManager_process_events(&net2);
627
628                 // Now send funds from 1 to 2!
629                 uint64_t channel_scid;
630                 while (true) {
631                         LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
632                         if (outbound_channels->datalen == 1) {
633                                 const LDKChannelDetails *channel = &outbound_channels->data[0];
634                                 LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
635                                 // Note that the channel ID is the same as the channel txid reversed as the output index is 0
636                                 uint8_t expected_chan_id[32];
637                                 for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
638                                 assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
639                                 assert(!memcmp(
640                                         ChannelCounterparty_get_node_id(&counterparty).compressed_form,
641                                         ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
642                                 assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
643                                 // We opened the channel with 1000 push_msat:
644                                 assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
645                                         40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
646                                 int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
647                                 if (inbound_capacity < 0) inbound_capacity = 0;
648                                 assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
649                                 assert(ChannelDetails_get_is_usable(channel));
650                                 LDK::COption_u64Z scid_opt = ChannelDetails_get_short_channel_id(channel);
651                                 assert(scid_opt->some);
652                                 channel_scid = scid_opt->some;
653                                 break;
654                         }
655                         std::this_thread::yield();
656                 }
657
658                 LDKCOption_u64Z min_value = {
659                         .tag = LDKCOption_u64Z_Some,
660                         .some = 5000,
661                 };
662                 LDK::CResult_InvoiceSignOrCreationErrorZ invoice = create_invoice_from_channelmanager(&cm2,
663                         KeysManager_as_KeysInterface(&keys2),
664                         LDKCurrency_Bitcoin, min_value,
665                         LDKStr {
666                                 .chars = (const uint8_t *)"Invoice Description",
667                                 .len =             strlen("Invoice Description"),
668                                 .chars_is_owned = false
669                         });
670                 assert(invoice->result_ok);
671                 LDKThirtyTwoBytes payment_hash;
672                 memcpy(payment_hash.data, Invoice_payment_hash(invoice->contents.result), 32);
673
674                 {
675                         LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
676                         LDK::NetworkGraph graph_2_ref = NetGraphMsgHandler_get_network_graph(&net_graph2);
677                         LDK::Score chan_scorer = LDKScore {
678                                 .this_arg = NULL, .channel_penalty_msat = get_chan_score, .free = NULL
679                         };
680                         LDK::CResult_RouteLightningErrorZ route = get_route(ChannelManager_get_our_node_id(&cm1), &graph_2_ref, ChannelManager_get_our_node_id(&cm2), LDKInvoiceFeatures {
681                                         .inner = NULL, .is_owned = false
682                                 }, &outbound_channels, Invoice_route_hints(invoice->contents.result),
683                                 5000, Invoice_min_final_cltv_expiry(invoice->contents.result), logger1, &chan_scorer);
684                         assert(route->result_ok);
685                         LDK::CVec_CVec_RouteHopZZ paths = Route_get_paths(route->contents.result);
686                         assert(paths->datalen == 1);
687                         assert(paths->data[0].datalen == 1);
688                         assert(!memcmp(RouteHop_get_pubkey(&paths->data[0].data[0]).compressed_form,
689                                 ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
690                         assert(RouteHop_get_short_channel_id(&paths->data[0].data[0]) == channel_scid);
691                         LDK::CResult_PaymentIdPaymentSendFailureZ send_res = ChannelManager_send_payment(&cm1, route->contents.result, payment_hash, Invoice_payment_secret(invoice->contents.result));
692                         assert(send_res->result_ok);
693                 }
694
695                 mons_updated = 0;
696                 PeerManager_process_events(&net1);
697                 while (mons_updated != 4) {
698                         std::this_thread::yield();
699                 }
700
701                 // Check that we received the payment!
702                 LDKEventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
703                 while (true) {
704                         EventQueue queue;
705                         LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
706                         ev2.process_pending_events(ev2.this_arg, handler);
707                         if (queue.events.size() == 1) {
708                                 assert(queue.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
709                                 break;
710                         }
711                         std::this_thread::yield();
712                 }
713                 ChannelManager_process_pending_htlc_forwards(&cm2);
714                 PeerManager_process_events(&net2);
715
716                 mons_updated = 0;
717                 LDKThirtyTwoBytes payment_preimage;
718                 {
719                         EventQueue queue;
720                         LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
721                         ev2.process_pending_events(ev2.this_arg, handler);
722                         assert(queue.events.size() == 1);
723                         assert(queue.events[0]->tag == LDKEvent_PaymentReceived);
724                         assert(!memcmp(queue.events[0]->payment_received.payment_hash.data, payment_hash.data, 32));
725                         assert(queue.events[0]->payment_received.purpose.tag == LDKPaymentPurpose_InvoicePayment);
726                         assert(!memcmp(queue.events[0]->payment_received.purpose.invoice_payment.payment_secret.data,
727                                         Invoice_payment_secret(invoice->contents.result).data, 32));
728                         assert(queue.events[0]->payment_received.amt == 5000);
729                         memcpy(payment_preimage.data, queue.events[0]->payment_received.purpose.invoice_payment.payment_preimage.data, 32);
730                         assert(ChannelManager_claim_funds(&cm2, payment_preimage));
731                 }
732                 PeerManager_process_events(&net2);
733                 // Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
734                 while (mons_updated != 5) {
735                         std::this_thread::yield();
736                 }
737                 {
738                         EventQueue queue;
739                         LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
740                         ev1.process_pending_events(ev1.this_arg, handler);
741                         assert(queue.events.size() == 1);
742                         assert(queue.events[0]->tag == LDKEvent_PaymentSent);
743                         assert(!memcmp(queue.events[0]->payment_sent.payment_preimage.data, payment_preimage.data, 32));
744                 }
745
746                 conn.stop();
747
748                 cm1_ser = ChannelManager_write(&cm1);
749                 cm2_ser = ChannelManager_write(&cm2);
750         }
751
752         LDK::CVec_ChannelMonitorZ mons_list1 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
753         assert(mons1.mons.size() == 1);
754         mons_list1->data[0] = *& std::get<1>(mons1.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
755         mons_list1->data[0].is_owned = false; // XXX: God this sucks
756         uint8_t node_seed[32];
757         memset(&node_seed, 0, 32);
758         LDK::KeysManager keys1 = KeysManager_new(&node_seed, 1, 0);
759         LDK::KeysInterface keys_source1 = KeysManager_as_KeysInterface(&keys1);
760
761         LDK::ChannelManagerReadArgs cm1_args = ChannelManagerReadArgs_new(KeysManager_as_KeysInterface(&keys1), fee_est, mon1, broadcast, logger1, UserConfig_default(), std::move(mons_list1));
762         LDK::CResult_C2Tuple_BlockHashChannelManagerZDecodeErrorZ cm1_read =
763                 C2Tuple_BlockHashChannelManagerZ_read(LDKu8slice { .data = cm1_ser->data, .datalen = cm1_ser -> datalen}, std::move(cm1_args));
764         assert(cm1_read->result_ok);
765         LDK::ChannelManager cm1(std::move(cm1_read->contents.result->b));
766
767         LDK::CVec_ChannelMonitorZ mons_list2 = LDKCVec_ChannelMonitorZ { .data = (LDKChannelMonitor*)malloc(sizeof(LDKChannelMonitor)), .datalen = 1 };
768         assert(mons2.mons.size() == 1);
769         mons_list2->data[0] = *& std::get<1>(mons2.mons[0]); // Note that we need a reference, thus need a raw clone here, which *& does.
770         mons_list2->data[0].is_owned = false; // XXX: God this sucks
771         memset(&node_seed, 1, 32);
772         LDK::KeysManager keys2 = KeysManager_new(&node_seed, 1, 0);
773
774         LDK::ChannelManagerReadArgs cm2_args = ChannelManagerReadArgs_new(KeysManager_as_KeysInterface(&keys2), fee_est, mon2, broadcast, logger2, UserConfig_default(), std::move(mons_list2));
775         LDK::CResult_C2Tuple_BlockHashChannelManagerZDecodeErrorZ cm2_read =
776                 C2Tuple_BlockHashChannelManagerZ_read(LDKu8slice { .data = cm2_ser->data, .datalen = cm2_ser -> datalen}, std::move(cm2_args));
777         assert(cm2_read->result_ok);
778         LDK::ChannelManager cm2(std::move(cm2_read->contents.result->b));
779
780         // Attempt to close the channel...
781         uint8_t chan_id[32];
782         for (int i = 0; i < 32; i++) { chan_id[i] = channel_open_txid[31-i]; }
783         LDK::CResult_NoneAPIErrorZ close_res = ChannelManager_close_channel(&cm1, &chan_id);
784         assert(!close_res->result_ok); // Note that we can't close while disconnected!
785
786         // Open a connection!
787         LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph1));
788         random_bytes = keys_source1->get_secure_random_bytes(keys_source1->this_arg);
789
790         LDKPublicKey chan_2_node_id = ChannelManager_get_our_node_id(&cm2);
791         LDKCustomMessageHandler custom_msg_handler1 = {
792                 .this_arg = &chan_2_node_id,
793                 .handle_custom_message = NULL, // We only create custom messages, not handle them
794                 .get_and_clear_pending_msg = create_custom_msg,
795                 .CustomMessageReader = LDKCustomMessageReader {
796                         .this_arg = NULL,
797                         .read = read_custom_message,
798                         .free = NULL,
799                 },
800                 .free = NULL,
801         };
802         LDK::PeerManager net1 = PeerManager_new(std::move(msg_handler1), node_secret1, &random_bytes.data, logger1, std::move(custom_msg_handler1));
803
804         LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph2));
805         CustomMsgQueue peer_2_custom_messages;
806         LDKCustomMessageHandler custom_msg_handler2 = {
807                 .this_arg = &peer_2_custom_messages,
808                 .handle_custom_message = handle_custom_message,
809                 .get_and_clear_pending_msg = never_send_custom_msgs,
810                 .CustomMessageReader = LDKCustomMessageReader {
811                         .this_arg = NULL,
812                         .read = read_custom_message,
813                         .free = NULL,
814                 },
815                 .free = NULL,
816         };
817         random_bytes = keys_source1->get_secure_random_bytes(keys_source1->this_arg);
818         LDK::PeerManager net2 = PeerManager_new(std::move(msg_handler2), node_secret2, &random_bytes.data, logger2, std::move(custom_msg_handler2));
819
820         PeersConnection conn(cm1, cm2, net1, net2);
821
822         while (true) {
823                 // Wait for the channels to be considered up once the reestablish messages are processed
824                 LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
825                 if (outbound_channels->datalen == 1) {
826                         break;
827                 }
828         }
829
830         // Actually close the channel
831         num_txs_broadcasted = 0;
832         close_res = ChannelManager_close_channel(&cm1, &chan_id);
833         assert(close_res->result_ok);
834         PeerManager_process_events(&net1);
835         while (num_txs_broadcasted != 2) {
836                 std::this_thread::yield();
837         }
838         LDK::CVec_ChannelDetailsZ chans_after_close1 = ChannelManager_list_channels(&cm1);
839         assert(chans_after_close1->datalen == 0);
840         LDK::CVec_ChannelDetailsZ chans_after_close2 = ChannelManager_list_channels(&cm2);
841         assert(chans_after_close2->datalen == 0);
842
843         conn.stop();
844
845         assert(peer_2_custom_messages.msgs.size() != 0);
846
847         // Few extra random tests:
848         LDKSecretKey sk;
849         memset(&sk, 42, 32);
850         LDKThirtyTwoBytes kdiv_params;
851         memset(&kdiv_params, 43, 32);
852         LDK::InMemorySigner signer = InMemorySigner_new(sk, sk, sk, sk, sk, random_bytes, 42, kdiv_params);
853 }