Merge pull request #38 from TheBlueMatt/main
[ldk-c-bindings] / lightning-c-bindings / demo.cpp
index 230d0c0c92f762ad7a30a840108f72ab052461b3..7c6dfda2e0f1c93ffbe83ba0a7dfbc9c0943ff53 100644 (file)
@@ -1,12 +1,17 @@
 extern "C" {
-#include "include/rust_types.h"
-#include "include/lightning.h"
+#include <lightning.h>
+
+#ifdef REAL_NET
+#include <ldk_net.h>
+#endif
 }
 #include "include/lightningpp.hpp"
 
 #include <assert.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <unistd.h>
 
 #include <atomic>
@@ -49,15 +54,13 @@ const uint8_t valid_node_announcement[] = {
 // A simple block containing only one transaction (which is the channel-open transaction for the
 // channel we'll create). This was originally created by printing additional data in a simple
 // rust-lightning unit test.
-const uint8_t channel_open_header[80] = {
+const uint8_t channel_open_block[] = {
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0xa2, 0x47, 0xd2, 0xf8, 0xd4, 0xe0, 0x6a, 0x3f, 0xf9, 0x7a, 0x9a, 0x34,
        0xbb, 0xa9, 0x96, 0xde, 0x63, 0x84, 0x5a, 0xce, 0xcf, 0x98, 0xb8, 0xbb, 0x75, 0x4c, 0x4f, 0x7d,
        0xee, 0x4c, 0xa9, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const uint8_t channel_open_tx[] = {
+       0x01, // transaction count
        0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -74,29 +77,21 @@ const uint8_t channel_open_txid[] = {
 };
 
 // Two blocks built on top of channel_open_block:
-const uint8_t header_1[80] = {
-       0x01, 0x00, 0x00, 0x00, 0x65, 0x8e, 0xf1, 0x90, 0x88, 0xfa, 0x13, 0x9c, 0x6a, 0xea, 0xf7, 0xc1,
-       0x5a, 0xdd, 0x52, 0x4d, 0x3c, 0x48, 0x03, 0xb3, 0x9b, 0x25, 0x4f, 0x02, 0x79, 0x05, 0x90, 0xe0,
-       0xc4, 0x8d, 0xa0, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+const uint8_t block_1[81] = {
+       0x01, 0x00, 0x00, 0x00, 0x0c, 0x7a, 0xc2, 0xdc, 0x08, 0xaf, 0x40, 0x7d, 0x58, 0x81, 0x9b, 0x44,
+       0xc7, 0xe0, 0x0f, 0x78, 0xc0, 0xd1, 0x01, 0xa2, 0x03, 0x16, 0x4a, 0x8d, 0x92, 0x66, 0x4e, 0xaf,
+       0x7f, 0xfc, 0x6e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, // transaction count
 };
-const uint8_t header_2[80] = {
-       0x01, 0x00, 0x00, 0x00, 0xf2, 0x08, 0x87, 0x51, 0xcb, 0xb1, 0x1a, 0x51, 0x76, 0x01, 0x6c, 0x5d,
-       0x76, 0x26, 0x54, 0x6f, 0xd9, 0xbd, 0xa6, 0xa5, 0xe9, 0x4b, 0x21, 0x6e, 0xda, 0xa3, 0x64, 0x23,
-       0xcd, 0xf1, 0xe2, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+const uint8_t block_2[81] = {
+       0x01, 0x00, 0x00, 0x00, 0x36, 0x0b, 0xf5, 0x46, 0x4a, 0xc7, 0x26, 0x4c, 0x4b, 0x36, 0xa6, 0x9d,
+       0x0e, 0xf0, 0x14, 0xfb, 0x8a, 0xcb, 0x20, 0x84, 0x18, 0xf3, 0xaa, 0x77, 0x32, 0x2d, 0xf7, 0x48,
+       0x62, 0x92, 0xb1, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const LDKThirtyTwoBytes payment_preimage_1 = {
-       .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 }
-};
-const LDKThirtyTwoBytes payment_hash_1 = {
-       .data = {
-               0xdc, 0xb1, 0xac, 0x4a, 0x5d, 0xe3, 0x70, 0xca, 0xd0, 0x91, 0xc1, 0x3f, 0x13, 0xae, 0xe2, 0xf9,
-               0x36, 0xc2, 0x78, 0xfa, 0x05, 0xd2, 0x64, 0x65, 0x3c, 0x0c, 0x13, 0x21, 0x85, 0x2a, 0x35, 0xe8
-       }
+       0x00, // transaction count
 };
 
 const LDKThirtyTwoBytes genesis_hash = { // We don't care particularly if this is "right"
@@ -137,7 +132,7 @@ struct NodeMonitors {
        void ConnectBlock(const uint8_t (*header)[80], uint32_t height, LDKCVec_C2Tuple_usizeTransactionZZ tx_data, LDKBroadcasterInterface broadcast, LDKFeeEstimator fee_est) {
                std::unique_lock<std::mutex> l(mut);
                for (auto& mon : mons) {
-                       LDK::CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ res = ChannelMonitor_block_connected(&mon.second, &header_2, tx_data, height, broadcast, fee_est, *logger);
+                       LDK::CVec_TransactionOutputsZ res = ChannelMonitor_block_connected(&mon.second, header, tx_data, height, broadcast, fee_est, *logger);
                }
        }
 };
@@ -196,6 +191,77 @@ LDKCVec_MonitorEventZ monitors_pending_monitor_events(const void *this_arg) {
        }
 }
 
+struct EventQueue {
+       std::vector<LDK::Event> events;
+};
+void handle_event(const void *this_arg, LDKEvent event) {
+       EventQueue* arg = (EventQueue*) this_arg;
+       arg->events.push_back(std::move(event));
+}
+
+#ifdef REAL_NET
+class PeersConnection {
+       void* node1_handler;
+       void* node2_handler;
+
+public:
+       PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
+               node1_handler = init_socket_handling(&net1);
+               node2_handler = init_socket_handling(&net2);
+
+               struct sockaddr_in listen_addr;
+               listen_addr.sin_family = AF_INET;
+               listen_addr.sin_addr.s_addr = htonl((127 << 8*3) | 1);
+               listen_addr.sin_port = htons(10042);
+               assert(!socket_bind(node2_handler, (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+               assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+               while (true) {
+                       // Wait for the initial handshakes to complete...
+                       LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+                       LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+                       if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
+                       std::this_thread::yield();
+               }
+
+               // Connect twice, which should auto-disconnect, and is a good test of our disconnect pipeline
+               assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+               assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+               // Then disconnect the "main" connection, while another connection is being made.
+               PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
+               assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+               // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
+               while (true) {
+                       PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
+                       // Wait for the peers to disconnect...
+                       LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+                       LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+                       if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
+                       std::this_thread::yield();
+               }
+
+               // Finally make an actual connection and keep it this time
+               assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+               while (true) {
+                       // Wait for the initial handshakes to complete...
+                       LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+                       LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+                       if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
+                       std::this_thread::yield();
+               }
+       }
+       void stop() {
+               interrupt_socket_handling(node1_handler);
+               interrupt_socket_handling(node2_handler);
+       }
+};
+
+#else // REAL_NET
+
 uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
        return write((int)((long)this_arg), data.data, data.datalen);
 }
@@ -242,7 +308,7 @@ public:
                        .disconnect_socket = sock_disconnect_socket,
                        .eq = sock_eq,
                        .hash = sock_hash,
-                       .clone = NULL,
+                       .cloned = NULL,
                        .free = NULL,
                };
 
@@ -252,7 +318,7 @@ public:
                        .disconnect_socket = sock_disconnect_socket,
                        .eq = sock_eq,
                        .hash = sock_hash,
-                       .clone = NULL,
+                       .cloned = NULL,
                        .free = NULL,
                };
 
@@ -286,8 +352,16 @@ public:
                t2.join();
        }
 };
+#endif // !REAL_NET
 
 int main() {
+       uint8_t channel_open_header[80];
+       uint8_t header_1[80];
+       uint8_t header_2[80];
+       memcpy(channel_open_header, channel_open_block, 80);
+       memcpy(header_1, block_1, 80);
+       memcpy(header_2, block_2, 80);
+
        LDKPublicKey null_pk;
        memset(&null_pk, 0, sizeof(null_pk));
 
@@ -354,7 +428,7 @@ int main() {
                LDK::KeysInterface keys_source1 = KeysManager_as_KeysInterface(&keys1);
                node_secret1 = keys_source1->get_node_secret(keys_source1->this_arg);
 
-               LDK::ChannelManager cm1 = ChannelManager_new(fee_est, mon1, broadcast, logger1, KeysManager_as_KeysInterface(&keys1), UserConfig_default(), ChainParameters_new(network, chain_tip, 0));
+               LDK::ChannelManager cm1 = ChannelManager_new(fee_est, mon1, broadcast, logger1, KeysManager_as_KeysInterface(&keys1), UserConfig_default(), ChainParameters_new(network, BestBlock_new(chain_tip, 0)));
 
                LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
                assert(channels->datalen == 0);
@@ -366,8 +440,8 @@ int main() {
 
                // Demo getting a channel key and check that its returning real pubkeys:
                LDK::Sign chan_signer1 = keys_source1->get_channel_signer(keys_source1->this_arg, false, 42);
-               chan_signer1->set_pubkeys(&chan_signer1); // Make sure pubkeys is defined
-               LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->pubkeys);
+               chan_signer1->BaseSign.set_pubkeys(&chan_signer1->BaseSign); // Make sure pubkeys is defined
+               LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->BaseSign.pubkeys);
                assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
 
                // Instantiate classes for node 2:
@@ -381,7 +455,7 @@ int main() {
                LDK::UserConfig config2 = UserConfig_default();
                UserConfig_set_own_channel_config(&config2, std::move(handshake_config2));
 
-               LDK::ChannelManager cm2 = ChannelManager_new(fee_est, mon2, broadcast, logger2, KeysManager_as_KeysInterface(&keys2), std::move(config2), ChainParameters_new(network, chain_tip, 0));
+               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)));
 
                LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
                assert(channels2->datalen == 0);
@@ -407,14 +481,16 @@ int main() {
 
                LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
                assert(new_channels->datalen == 1);
-               LDKPublicKey chan_open_pk = ChannelDetails_get_remote_network_id(&new_channels->data[0]);
+               LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
+               LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
                assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
 
                while (true) {
                        LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
                        if (new_channels_2->datalen == 1) {
                                // Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
-                               const LDK::InitFeatures init_feats = ChannelDetails_get_counterparty_features(&new_channels_2->data[0]);
+                               LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
+                               const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
                                assert(init_feats->inner != NULL);
                                break;
                        }
@@ -423,17 +499,19 @@ int main() {
 
                LDKEventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
                while (true) {
-                       LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
-                       if (events->datalen == 1) {
-                               assert(events->data[0].tag == LDKEvent_FundingGenerationReady);
-                               assert(events->data[0].funding_generation_ready.user_channel_id == 42);
-                               assert(events->data[0].funding_generation_ready.channel_value_satoshis == 40000);
-                               assert(events->data[0].funding_generation_ready.output_script.datalen == 34);
-                               assert(!memcmp(events->data[0].funding_generation_ready.output_script.data, channel_open_tx + 58, 34));
-                               LDKThirtyTwoBytes txid;
-                               for (int i = 0; i < 32; i++) { txid.data[i] = channel_open_txid[31-i]; }
-                               LDK::OutPoint outp = OutPoint_new(txid, 0);
-                               ChannelManager_funding_transaction_generated(&cm1, &events->data[0].funding_generation_ready.temporary_channel_id.data, std::move(outp));
+                       EventQueue queue;
+                       LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
+                       ev1.process_pending_events(ev1.this_arg, handler);
+                       if (queue.events.size() == 1) {
+                               assert(queue.events[0]->tag == LDKEvent_FundingGenerationReady);
+                               assert(queue.events[0]->funding_generation_ready.user_channel_id == 42);
+                               assert(queue.events[0]->funding_generation_ready.channel_value_satoshis == 40000);
+                               assert(queue.events[0]->funding_generation_ready.output_script.datalen == 34);
+                               assert(!memcmp(queue.events[0]->funding_generation_ready.output_script.data, channel_open_block + 58 + 81, 34));
+                               LDKTransaction funding_transaction { .data = const_cast<uint8_t*>(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false };
+
+                               LDK::CResult_NoneAPIErrorZ fund_res = ChannelManager_funding_transaction_generated(&cm1, &queue.events[0]->funding_generation_ready.temporary_channel_id.data, funding_transaction);
+                               assert(fund_res->result_ok);
                                break;
                        }
                        std::this_thread::yield();
@@ -441,40 +519,33 @@ int main() {
 
                // We observe when the funding signed messages have been exchanged by
                // waiting for two monitors to be registered.
+               assert(num_txs_broadcasted == 0);
                PeerManager_process_events(&net1);
-               while (true) {
-                       LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
-                       if (events->datalen == 1) {
-                               assert(events->data[0].tag == LDKEvent_FundingBroadcastSafe);
-                               assert(events->data[0].funding_broadcast_safe.user_channel_id == 42);
-                               break;
-                       }
+               while (num_txs_broadcasted != 1) {
                        std::this_thread::yield();
                }
 
-               LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
-               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false });
-               ChannelManager_block_connected(&cm1, &channel_open_header, txdata, 1);
+               LDK::Listen listener1 = ChannelManager_as_Listen(&cm1);
+               listener1->block_connected(listener1->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
 
-               txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
-               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false });
-               ChannelManager_block_connected(&cm2, &channel_open_header, txdata, 1);
+               LDK::Listen listener2 = ChannelManager_as_Listen(&cm2);
+               listener2->block_connected(listener2->this_arg, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
 
-               txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
-               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false });
+               LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
+               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
                mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
 
                txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2Tuple_usizeTransactionZ*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 };
-               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false });
+               *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_block + 81, .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false });
                mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est);
 
-               ChannelManager_block_connected(&cm1, &header_1, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, 2);
-               ChannelManager_block_connected(&cm2, &header_1, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, 2);
+               listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
+               listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
                mons1.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
                mons2.ConnectBlock(&header_1, 2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
 
-               ChannelManager_block_connected(&cm1, &header_2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, 3);
-               ChannelManager_block_connected(&cm2, &header_2, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, 3);
+               listener1->block_connected(listener1->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
+               listener2->block_connected(listener2->this_arg, LDKu8slice { .data = block_2, .datalen = sizeof(block_1) }, 3);
                mons1.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
                mons2.ConnectBlock(&header_2, 3, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, broadcast, fee_est);
 
@@ -486,33 +557,53 @@ int main() {
                        LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
                        if (outbound_channels->datalen == 1) {
                                const LDKChannelDetails *channel = &outbound_channels->data[0];
+                               LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
                                // Note that the channel ID is the same as the channel txid reversed as the output index is 0
                                uint8_t expected_chan_id[32];
                                for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
                                assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
-                               assert(!memcmp(ChannelDetails_get_remote_network_id(channel).compressed_form,
-                                               ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
+                               assert(!memcmp(
+                                       ChannelCounterparty_get_node_id(&counterparty).compressed_form,
+                                       ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
                                assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
                                // We opened the channel with 1000 push_msat:
-                               assert(ChannelDetails_get_outbound_capacity_msat(channel) == 40000*1000 - 1000);
-                               assert(ChannelDetails_get_inbound_capacity_msat(channel) == 1000);
-                               assert(ChannelDetails_get_is_live(channel));
+                               assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
+                                       40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
+                               int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
+                               if (inbound_capacity < 0) inbound_capacity = 0;
+                               assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
+                               assert(ChannelDetails_get_is_usable(channel));
                                break;
                        }
                        std::this_thread::yield();
                }
 
-               LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
-               LDKThirtyTwoBytes payment_secret;
-               memset(payment_secret.data, 0x42, 32);
+               LDKCOption_u64Z min_value = {
+                       .tag = LDKCOption_u64Z_Some,
+                       .some = 5000,
+               };
+               LDK::CResult_InvoiceSignOrCreationErrorZ invoice = create_invoice_from_channelmanager(&cm2,
+                       KeysManager_as_KeysInterface(&keys2),
+                       LDKCurrency_Bitcoin, min_value,
+                       LDKStr {
+                               .chars = (const uint8_t *)"Invoice Description",
+                               .len =             strlen("Invoice Description"),
+                               .chars_is_owned = false
+                       });
+               assert(invoice->result_ok);
+               LDKThirtyTwoBytes payment_hash;
+               memcpy(payment_hash.data, Invoice_payment_hash(invoice->contents.result), 32);
+
                {
+                       LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
                        LDK::LockedNetworkGraph graph_2_locked = NetGraphMsgHandler_read_locked_graph(&net_graph2);
                        LDK::NetworkGraph graph_2_ref = LockedNetworkGraph_graph(&graph_2_locked);
-                       LDK::CResult_RouteLightningErrorZ route = get_route(ChannelManager_get_our_node_id(&cm1), &graph_2_ref, ChannelManager_get_our_node_id(&cm2), &outbound_channels, LDKCVec_RouteHintZ {
-                                       .data = NULL, .datalen = 0
-                               }, 5000, 10, logger1);
+                       LDK::CResult_RouteLightningErrorZ route = get_route(ChannelManager_get_our_node_id(&cm1), &graph_2_ref, ChannelManager_get_our_node_id(&cm2), LDKInvoiceFeatures {
+                                       .inner = NULL, .is_owned = false
+                               }, &outbound_channels, Invoice_route_hints(invoice->contents.result),
+                               5000, Invoice_min_final_cltv_expiry(invoice->contents.result), logger1);
                        assert(route->result_ok);
-                       LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment(&cm1, route->contents.result, payment_hash_1, payment_secret);
+                       LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment(&cm1, route->contents.result, payment_hash, Invoice_payment_secret(invoice->contents.result));
                        assert(send_res->result_ok);
                }
 
@@ -525,9 +616,11 @@ int main() {
                // Check that we received the payment!
                LDKEventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
                while (true) {
-                       LDK::CVec_EventZ events = ev2.get_and_clear_pending_events(ev2.this_arg);
-                       if (events->datalen == 1) {
-                               assert(events->data[0].tag == LDKEvent_PendingHTLCsForwardable);
+                       EventQueue queue;
+                       LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
+                       ev2.process_pending_events(ev2.this_arg, handler);
+                       if (queue.events.size() == 1) {
+                               assert(queue.events[0]->tag == LDKEvent_PendingHTLCsForwardable);
                                break;
                        }
                        std::this_thread::yield();
@@ -536,14 +629,20 @@ int main() {
                PeerManager_process_events(&net2);
 
                mons_updated = 0;
+               LDKThirtyTwoBytes payment_preimage;
                {
-                       LDK::CVec_EventZ events = ev2.get_and_clear_pending_events(ev2.this_arg);
-                       assert(events->datalen == 1);
-                       assert(events->data[0].tag == LDKEvent_PaymentReceived);
-                       assert(!memcmp(events->data[0].payment_received.payment_hash.data, payment_hash_1.data, 32));
-                       assert(!memcmp(events->data[0].payment_received.payment_secret.data, payment_secret.data, 32));
-                       assert(events->data[0].payment_received.amt == 5000);
-                       assert(ChannelManager_claim_funds(&cm2, payment_preimage_1, payment_secret, 5000));
+                       EventQueue queue;
+                       LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
+                       ev2.process_pending_events(ev2.this_arg, handler);
+                       assert(queue.events.size() == 1);
+                       assert(queue.events[0]->tag == LDKEvent_PaymentReceived);
+                       assert(!memcmp(queue.events[0]->payment_received.payment_hash.data, payment_hash.data, 32));
+                       assert(queue.events[0]->payment_received.purpose.tag == LDKPaymentPurpose_InvoicePayment);
+                       assert(!memcmp(queue.events[0]->payment_received.purpose.invoice_payment.payment_secret.data,
+                                       Invoice_payment_secret(invoice->contents.result).data, 32));
+                       assert(queue.events[0]->payment_received.amt == 5000);
+                       memcpy(payment_preimage.data, queue.events[0]->payment_received.purpose.invoice_payment.payment_preimage.data, 32);
+                       assert(ChannelManager_claim_funds(&cm2, payment_preimage));
                }
                PeerManager_process_events(&net2);
                // Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
@@ -551,10 +650,12 @@ int main() {
                        std::this_thread::yield();
                }
                {
-                       LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
-                       assert(events->datalen == 1);
-                       assert(events->data[0].tag == LDKEvent_PaymentSent);
-                       assert(!memcmp(events->data[0].payment_sent.payment_preimage.data, payment_preimage_1.data, 32));
+                       EventQueue queue;
+                       LDKEventHandler handler = { .this_arg = &queue, .handle_event = handle_event, .free = NULL };
+                       ev1.process_pending_events(ev1.this_arg, handler);
+                       assert(queue.events.size() == 1);
+                       assert(queue.events[0]->tag == LDKEvent_PaymentSent);
+                       assert(!memcmp(queue.events[0]->payment_sent.payment_preimage.data, payment_preimage.data, 32));
                }
 
                conn.stop();
@@ -617,10 +718,10 @@ int main() {
        }
 
        // Actually close the channel
+       num_txs_broadcasted = 0;
        close_res = ChannelManager_close_channel(&cm1, &chan_id);
        assert(close_res->result_ok);
        PeerManager_process_events(&net1);
-       num_txs_broadcasted = 0;
        while (num_txs_broadcasted != 2) {
                std::this_thread::yield();
        }