[Java] Update batteries and tests to 0.0.108
[ldk-java] / src / test / java / org / ldk / PeerTest.java
1 package org.ldk;
2
3 import org.bitcoinj.core.*;
4 import org.bitcoinj.script.Script;
5 import org.junit.jupiter.api.Test;
6 import org.ldk.enums.Network;
7 import org.ldk.enums.Recipient;
8 import org.ldk.impl.bindings;
9
10 import java.lang.ref.Reference;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ConcurrentLinkedQueue;
17
18 public class PeerTest {
19     class Peer {
20         final long logger;
21         final long fee_estimator;
22         final long tx_broadcaster;
23         final long chain_monitor;
24         final long keys;
25         final long keys_interface;
26         final long config;
27         final long chan_manager;
28         final long chan_manager_events;
29         final long chan_handler;
30         final long router;
31         final long router_wrapper;
32         final long route_handler;
33         final long message_handler;
34         final long custom_message_handler;
35         final long peer_manager;
36         HashMap<String, Long> monitors; // Wow I forgot just how terrible Java is - we can't put a byte array here.
37         byte[] node_id;
38         bindings.LDKFeeEstimator fee_est;
39         bindings.LDKBroadcasterInterface broad_trait;
40         bindings.LDKLogger log_trait;
41         bindings.LDKWatch watcher;
42
43         Peer(byte seed) {
44             this.log_trait = (long arg) -> {
45                 System.out.println(seed + ": " + bindings.Record_get_args(arg));
46                 bindings.Record_free(arg);
47             };
48             logger = bindings.LDKLogger_new(this.log_trait);
49             this.fee_est = confirmation_target -> 0;
50             this.fee_estimator = bindings.LDKFeeEstimator_new(this.fee_est);
51             this.broad_trait = tx -> {
52                 // We should broadcast
53             };
54             this.tx_broadcaster = bindings.LDKBroadcasterInterface_new(this.broad_trait);
55             this.monitors = new HashMap<>();
56             this.watcher = new bindings.LDKWatch() {
57                 @Override
58                 public long watch_channel(long funding_txo, long monitor) {
59                     synchronized (monitors) {
60                         assert monitors.put(Arrays.toString(bindings.OutPoint_get_txid(funding_txo)), monitor) == null;
61                     }
62                     bindings.OutPoint_free(funding_txo);
63                     return bindings.CResult_NoneChannelMonitorUpdateErrZ_ok();
64                 }
65
66                 @Override
67                 public long update_channel(long funding_txo, long update) {
68                     synchronized (monitors) {
69                         String txid = Arrays.toString(bindings.OutPoint_get_txid(funding_txo));
70                         assert monitors.containsKey(txid);
71                         long update_res = bindings.ChannelMonitor_update_monitor(monitors.get(txid), update, tx_broadcaster, fee_estimator, logger);
72                         assert bindings.CResult_NoneNoneZ_is_ok(update_res);
73                         bindings.CResult_NoneNoneZ_free(update_res);
74                     }
75                     bindings.OutPoint_free(funding_txo);
76                     bindings.ChannelMonitorUpdate_free(update);
77                     return bindings.CResult_NoneChannelMonitorUpdateErrZ_ok();
78                 }
79
80                 @Override
81                 public long[] release_pending_monitor_events() {
82                     synchronized (monitors) {
83                         assert monitors.size() <= 1;
84                         for (Long mon : monitors.values()) {
85                             long funding_info = bindings.ChannelMonitor_get_funding_txo(mon);
86                             long funding_txo = bindings.C2Tuple_OutPointScriptZ_get_a(funding_info);
87                             long[] mon_events = bindings.ChannelMonitor_get_and_clear_pending_monitor_events(mon);
88                             long funding_mon_tuple = bindings.C2Tuple_OutPointCVec_MonitorEventZZ_new(funding_txo, mon_events);
89                             bindings.C2Tuple_OutPointScriptZ_free(funding_info);
90                             return new long[] {funding_mon_tuple};
91                         }
92                     }
93                     return new long[0];
94                 }
95             };
96             this.chain_monitor = bindings.LDKWatch_new(this.watcher);
97
98             byte[] key_seed = new byte[32];
99             for (byte i = 0; i < 32; i++) { key_seed[i] = (byte) (i ^ seed); }
100             this.keys = bindings.KeysManager_new(key_seed, System.currentTimeMillis() / 1000, (int)(System.currentTimeMillis() * 1000) & 0xffffffff);
101             this.keys_interface = bindings.KeysManager_as_KeysInterface(keys);
102             this.config = bindings.UserConfig_default();
103             long params = bindings.ChainParameters_new(Network.LDKNetwork_Bitcoin, bindings.BestBlock_new(new byte[32], 0));
104             this.chan_manager = bindings.ChannelManager_new(fee_estimator, chain_monitor, tx_broadcaster, logger, keys_interface, config, params);
105             this.node_id = bindings.ChannelManager_get_our_node_id(chan_manager);
106             this.chan_manager_events = bindings.ChannelManager_as_EventsProvider(chan_manager);
107
108             this.chan_handler = bindings.ChannelManager_as_ChannelMessageHandler(chan_manager);
109             this.router = bindings.NetworkGraph_new(new byte[32], logger);
110             this.router_wrapper = bindings.P2PGossipSync_new(router, bindings.COption_AccessZ_none(), logger);
111             this.route_handler = bindings.P2PGossipSync_as_RoutingMessageHandler(router_wrapper);
112             this.message_handler = bindings.MessageHandler_new(chan_handler, route_handler);
113             this.custom_message_handler = bindings.IgnoringMessageHandler_new();
114
115             byte[] random_data = new byte[32];
116             for (byte i = 0; i < 32; i++) { random_data[i] = (byte) ((i ^ seed) ^ 0xf0); }
117
118             long node_id_result = bindings.KeysInterface_get_node_secret(keys_interface, Recipient.LDKRecipient_Node);
119             assert bindings.CResult_SecretKeyNoneZ_is_ok(node_id_result);
120             this.peer_manager = bindings.PeerManager_new(message_handler, bindings.CResult_SecretKeyNoneZ_get_ok(node_id_result),
121                     random_data, logger, bindings.IgnoringMessageHandler_as_CustomMessageHandler(this.custom_message_handler));
122             bindings.CResult_SecretKeyNoneZ_free(node_id_result);
123         }
124
125         void connect_block(Block b, Transaction t, int height) {
126             long listen = bindings.ChannelManager_as_Listen(chan_manager);
127             bindings.Listen_block_connected(listen, b.bitcoinSerialize(), height);
128             bindings.Listen_free(listen);
129             synchronized (monitors) {
130                 for (Long mon : monitors.values()) {
131                     long[] txn;
132                     if (t != null)
133                         txn = new long[]{bindings.C2Tuple_usizeTransactionZ_new(1, t.bitcoinSerialize())};
134                     else
135                         txn = new long[0];
136                     byte[] header = Arrays.copyOfRange(b.bitcoinSerialize(), 0, 80);
137                     long[] ret = bindings.ChannelMonitor_block_connected(mon, header, txn, height, tx_broadcaster, fee_estimator, logger);
138                     for (long r : ret) {
139                         bindings.C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_free(r);
140                     }
141                 }
142             }
143         }
144
145         void free() {
146             // Note that we can't rely on finalizer order, so don't bother trying to rely on it here
147             bindings.Logger_free(logger);
148             bindings.FeeEstimator_free(fee_estimator);
149             bindings.BroadcasterInterface_free(tx_broadcaster);
150             bindings.Watch_free(chain_monitor);
151             bindings.KeysManager_free(keys);
152             bindings.KeysInterface_free(keys_interface);
153             bindings.UserConfig_free(config);
154             bindings.ChannelManager_free(chan_manager);
155             bindings.EventsProvider_free(chan_manager_events);
156             bindings.ChannelMessageHandler_free(chan_handler);
157             bindings.NetworkGraph_free(router);
158             bindings.P2PGossipSync_free(router_wrapper);
159             bindings.RoutingMessageHandler_free(route_handler);
160             //MessageHandler was actually moved into the route_handler!: bindings.MessageHandler_free(message_handler);
161             bindings.PeerManager_free(peer_manager);
162             synchronized (monitors) {
163                 for (Long mon : monitors.values()) {
164                     bindings.ChannelMonitor_free(mon);
165                 }
166             }
167         }
168     }
169
170     class LongHolder { long val; }
171     class PendingWrite {
172         long pm;
173         long descriptor;
174         byte[] array;
175         PendingWrite(long pm, long descriptor, byte[] array) { this.pm = pm; this.descriptor = descriptor; this.array = array; }
176         void process() {
177             long res = bindings.PeerManager_read_event(pm, descriptor, array);
178             assert bindings.CResult_boolPeerHandleErrorZ_is_ok(res);
179             assert !bindings.CResult_boolPeerHandleErrorZ_get_ok(res);
180             bindings.CResult_boolPeerHandleErrorZ_free(res);
181         }
182     }
183     ConcurrentLinkedQueue<PendingWrite> pending_writes = new ConcurrentLinkedQueue<>();
184
185     void do_read_event(ConcurrentLinkedQueue<Thread> list, long pm, long descriptor, byte[] arr) {
186         pending_writes.add(new PendingWrite(pm, descriptor, arr));
187         Thread thread = new Thread(() -> {
188             synchronized (pending_writes) {
189                 while (true) {
190                     PendingWrite write = pending_writes.poll();
191                     if (write == null) break;
192                     write.process();
193                 }
194             }
195         });
196         thread.start();
197         list.add(thread);
198     }
199
200     void deliver_peer_messages(ConcurrentLinkedQueue<Thread> list, long peer1, long peer2) throws InterruptedException {
201         bindings.PeerManager_process_events(peer1);
202         bindings.PeerManager_process_events(peer2);
203         while (!list.isEmpty()) {
204             list.poll().join();
205             bindings.PeerManager_process_events(peer1);
206             bindings.PeerManager_process_events(peer2);
207         }
208     }
209
210     @Test
211     void test_message_handler() throws InterruptedException {
212         Peer peer1 = new Peer((byte) 1);
213         Peer peer2 = new Peer((byte) 2);
214
215         ConcurrentLinkedQueue<Thread> list = new ConcurrentLinkedQueue<Thread>();
216         LongHolder descriptor1 = new LongHolder();
217         LongHolder descriptor1ref = descriptor1;
218         bindings.LDKSocketDescriptor sock1 = new bindings.LDKSocketDescriptor() {
219             @Override
220             public long send_data(byte[] data, boolean resume_read) {
221                 do_read_event(list, peer1.peer_manager, descriptor1ref.val, data);
222                 return data.length;
223             }
224
225             @Override public void disconnect_socket() { assert false; }
226             @Override public boolean eq(long other_arg) { boolean ret = bindings.SocketDescriptor_hash(other_arg) == 2; bindings.SocketDescriptor_free(other_arg); return ret; }
227             @Override public long hash() { return 2; }
228         };
229         long descriptor2 = bindings.LDKSocketDescriptor_new(sock1);
230
231         bindings.LDKSocketDescriptor sock2 = new bindings.LDKSocketDescriptor() {
232             @Override
233             public long send_data(byte[] data, boolean resume_read) {
234                 do_read_event(list, peer2.peer_manager, descriptor2, data);
235                 return data.length;
236             }
237
238             @Override public void disconnect_socket() { assert false; }
239             @Override public boolean eq(long other_arg) { boolean ret = bindings.SocketDescriptor_hash(other_arg) == 1; bindings.SocketDescriptor_free(other_arg); return ret; }
240             @Override public long hash() { return 1; }
241         };
242         descriptor1.val = bindings.LDKSocketDescriptor_new(sock2);
243
244         long no_netaddr = bindings.COption_NetAddressZ_none();
245         long init_vec = bindings.PeerManager_new_outbound_connection(peer1.peer_manager, peer2.node_id, descriptor1.val, no_netaddr);
246         assert(bindings.CResult_CVec_u8ZPeerHandleErrorZ_is_ok(init_vec));
247
248         long con_res = bindings.PeerManager_new_inbound_connection(peer2.peer_manager, descriptor2, no_netaddr);
249         assert(bindings.CResult_NonePeerHandleErrorZ_is_ok(con_res));
250         bindings.CResult_NonePeerHandleErrorZ_free(con_res);
251         do_read_event(list, peer2.peer_manager, descriptor2, bindings.CResult_CVec_u8ZPeerHandleErrorZ_get_ok(init_vec));
252         bindings.CResult_CVec_u8ZPeerHandleErrorZ_free(init_vec);
253         bindings.COption_NetAddressZ_free(no_netaddr);
254
255         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
256
257         long cc_res = bindings.ChannelManager_create_channel(peer1.chan_manager, peer2.node_id, 10000, 1000, 42, 0);
258         assert bindings.CResult_NoneAPIErrorZ_is_ok(cc_res);
259         bindings.CResult_NoneAPIErrorZ_free(cc_res);
260
261         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
262
263         ArrayList<Long> events = new ArrayList();
264         bindings.LDKEventHandler events_adder = events::add;
265         long handler = bindings.LDKEventHandler_new(events_adder);
266
267         bindings.EventsProvider_process_pending_events(peer1.chan_manager_events, handler);
268         assert events.size() == 1;
269         bindings.LDKEvent event = bindings.LDKEvent_ref_from_ptr(events.get(0));
270         assert event instanceof bindings.LDKEvent.FundingGenerationReady;
271         assert ((bindings.LDKEvent.FundingGenerationReady)event).channel_value_satoshis == 10000;
272         assert ((bindings.LDKEvent.FundingGenerationReady)event).user_channel_id == 42;
273         byte[] funding_spk = ((bindings.LDKEvent.FundingGenerationReady)event).output_script;
274         assert funding_spk.length == 34 && funding_spk[0] == 0 && funding_spk[1] == 32; // P2WSH
275         byte[] chan_id = ((bindings.LDKEvent.FundingGenerationReady)event).temporary_channel_id;
276         bindings.Event_free(events.remove(0));
277
278         Transaction funding = new Transaction(NetworkParameters.fromID(NetworkParameters.ID_MAINNET));
279         funding.addInput(new TransactionInput(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), funding, new byte[0]));
280         funding.getInputs().get(0).setWitness(new TransactionWitness(2)); // Make sure we don't complain about lack of witness
281         funding.getInput(0).getWitness().setPush(0, new byte[] {0x1});
282         funding.addOutput(Coin.SATOSHI.multiply(10000), new Script(funding_spk));
283         bindings.ChannelManager_funding_transaction_generated(peer1.chan_manager, chan_id, peer2.node_id, funding.bitcoinSerialize());
284
285         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
286
287         Block b = new Block(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), 2, Sha256Hash.ZERO_HASH, Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{funding}));
288         peer1.connect_block(b, funding, 1);
289         peer2.connect_block(b, funding, 1);
290
291         for (int height = 2; height < 10; height++) {
292             b = new Block(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[0]));
293             peer1.connect_block(b, null, height);
294             peer2.connect_block(b, null, height);
295         }
296
297         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
298
299         long[] peer1_chans = bindings.ChannelManager_list_channels(peer1.chan_manager);
300         long[] peer2_chans = bindings.ChannelManager_list_channels(peer2.chan_manager);
301         assert peer1_chans.length == 1;
302         assert peer2_chans.length == 1;
303         assert bindings.ChannelDetails_get_channel_value_satoshis(peer1_chans[0]) == 10000;
304         assert bindings.ChannelDetails_get_is_usable(peer1_chans[0]);
305         assert Arrays.equals(bindings.ChannelDetails_get_channel_id(peer1_chans[0]), funding.getTxId().getReversedBytes());
306         assert Arrays.equals(bindings.ChannelDetails_get_channel_id(peer2_chans[0]), funding.getTxId().getReversedBytes());
307         for (long chan : peer2_chans) bindings.ChannelDetails_free(chan);
308
309         long no_min_val = bindings.COption_u64Z_none();
310         long inbound_payment = bindings.ChannelManager_create_inbound_payment(peer2.chan_manager, no_min_val, 7200);
311         assert bindings.CResult_C2Tuple_PaymentHashPaymentSecretZNoneZ_is_ok(inbound_payment);
312         long payment_tuple = bindings.CResult_C2Tuple_PaymentHashPaymentSecretZNoneZ_get_ok(inbound_payment);
313         bindings.COption_u64Z_free(no_min_val);
314
315         long scorer = bindings.ProbabilisticScorer_new(bindings.ProbabilisticScoringParameters_default(), peer1.router, peer1.logger);
316         long scorer_interface = bindings.ProbabilisticScorer_as_Score(scorer);
317
318         long no_u64 = bindings.COption_u64Z_none();
319         long invoice_features = bindings.InvoiceFeatures_known();
320         long payee = bindings.PaymentParameters_new(peer2.node_id, invoice_features, new long[0], no_u64, 6*24*14);
321         bindings.InvoiceFeatures_free(invoice_features);
322         bindings.COption_u64Z_free(no_u64);
323         long route_params = bindings.RouteParameters_new(payee, 1000, 42);
324         long route = bindings.find_route(peer1.node_id, route_params, peer1.router, peer1_chans, peer1.logger,
325                 scorer_interface, new byte[32]);
326         bindings.RouteParameters_free(route_params);
327         bindings.PaymentParameters_free(payee);
328         bindings.Score_free(scorer_interface);
329         bindings.ProbabilisticScorer_free(scorer);
330
331         for (long chan : peer1_chans) bindings.ChannelDetails_free(chan);
332         assert bindings.CResult_RouteLightningErrorZ_is_ok(route);
333         long payment_res = bindings.ChannelManager_send_payment(peer1.chan_manager, bindings.CResult_RouteLightningErrorZ_get_ok(route),
334                 bindings.C2Tuple_PaymentHashPaymentSecretZ_get_a(payment_tuple), bindings.C2Tuple_PaymentHashPaymentSecretZ_get_b(payment_tuple));
335         bindings.CResult_RouteLightningErrorZ_free(route);
336         bindings.CResult_C2Tuple_PaymentHashPaymentSecretZNoneZ_is_ok(inbound_payment);
337         assert bindings.CResult_NonePaymentSendFailureZ_is_ok(payment_res);
338         bindings.CResult_NonePaymentSendFailureZ_free(payment_res);
339
340         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
341
342         bindings.EventsProvider_process_pending_events(peer2.chan_manager_events, handler);
343         assert events.size() == 1;
344         bindings.LDKEvent forwardable = bindings.LDKEvent_ref_from_ptr(events.get(0));
345         assert forwardable instanceof bindings.LDKEvent.PendingHTLCsForwardable;
346         bindings.Event_free(events.remove(0));
347         bindings.ChannelManager_process_pending_htlc_forwards(peer2.chan_manager);
348
349         bindings.EventsProvider_process_pending_events(peer2.chan_manager_events, handler);
350         assert events.size() == 1;
351         bindings.LDKEvent payment_recvd = bindings.LDKEvent_ref_from_ptr(events.get(0));
352         assert payment_recvd instanceof bindings.LDKEvent.PaymentReceived;
353         bindings.LDKPaymentPurpose purpose = bindings.LDKPaymentPurpose_ref_from_ptr(((bindings.LDKEvent.PaymentReceived) payment_recvd).purpose);
354         assert purpose instanceof bindings.LDKPaymentPurpose.InvoicePayment;
355         bindings.ChannelManager_claim_funds(peer2.chan_manager, ((bindings.LDKPaymentPurpose.InvoicePayment) purpose).payment_preimage);
356         bindings.Event_free(events.remove(0));
357
358         bindings.EventsProvider_process_pending_events(peer2.chan_manager_events, handler);
359         assert events.size() == 1;
360         bindings.LDKEvent payment_claimed = bindings.LDKEvent_ref_from_ptr(events.get(0));
361         assert payment_claimed instanceof bindings.LDKEvent.PaymentClaimed;
362         bindings.Event_free(events.remove(0));
363
364         deliver_peer_messages(list, peer1.peer_manager, peer2.peer_manager);
365
366         bindings.EventsProvider_process_pending_events(peer1.chan_manager_events, handler);
367         assert events.size() == 2;
368         bindings.LDKEvent sent = bindings.LDKEvent_ref_from_ptr(events.get(0));
369         assert sent instanceof bindings.LDKEvent.PaymentSent;
370         bindings.Event_free(events.remove(0));
371         bindings.LDKEvent sent_path = bindings.LDKEvent_ref_from_ptr(events.get(0));
372         assert sent_path instanceof bindings.LDKEvent.PaymentPathSuccessful;
373         bindings.Event_free(events.remove(0));
374         Reference.reachabilityFence(events_adder);
375
376         bindings.EventHandler_free(handler);
377
378         peer1.free();
379         peer2.free();
380         bindings.SocketDescriptor_free(descriptor2);
381         bindings.SocketDescriptor_free(descriptor1.val);
382     }
383 }