X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Forg%2Fldk%2FPeerTest.java;h=40ebe3056739feea05eeb6cfada68bdc0541df26;hb=9e1ceb0850f7c6f42a15e20c25925fd1961a8476;hp=8ff630d75b04d5d8d2f944bbfcc02092b1a8e65f;hpb=d478eefde9ef918c4f30f5235c5e53b246a8865b;p=ldk-java diff --git a/src/test/java/org/ldk/PeerTest.java b/src/test/java/org/ldk/PeerTest.java index 8ff630d7..40ebe305 100644 --- a/src/test/java/org/ldk/PeerTest.java +++ b/src/test/java/org/ldk/PeerTest.java @@ -1,9 +1,16 @@ package org.ldk; +import org.bitcoinj.core.*; +import org.bitcoinj.script.Script; import org.junit.jupiter.api.Test; import org.ldk.impl.bindings; import org.ldk.enums.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; public class PeerTest { @@ -22,6 +29,8 @@ public class PeerTest { final long route_handler; final long message_handler; final long peer_manager; + HashMap monitors; // Wow I forgot just how terrible Java is - we can't put a byte array here. + byte[] node_id; Peer(byte seed) { logger = bindings.LDKLogger_new((String arg)-> System.out.println(seed + ": " + arg)); @@ -29,19 +38,39 @@ public class PeerTest { this.tx_broadcaster = bindings.LDKBroadcasterInterface_new(tx -> { // We should broadcast }); + this.monitors = new HashMap<>(); this.chain_monitor = bindings.LDKWatch_new(new bindings.LDKWatch() { @Override public long watch_channel(long funding_txo, long monitor) { + synchronized (monitors) { + assert monitors.put(Arrays.toString(bindings.OutPoint_get_txid(funding_txo)), monitor) == null; + } + bindings.OutPoint_free(funding_txo); return bindings.CResult_NoneChannelMonitorUpdateErrZ_ok(); } @Override public long update_channel(long funding_txo, long update) { + synchronized (monitors) { + String txid = Arrays.toString(bindings.OutPoint_get_txid(funding_txo)); + assert monitors.containsKey(txid); + long update_res = bindings.ChannelMonitor_update_monitor(monitors.get(txid), update, tx_broadcaster, logger); + assert bindings.LDKCResult_NoneMonitorUpdateErrorZ_result_ok(update_res); + bindings.CResult_NoneMonitorUpdateErrorZ_free(update_res); + } + bindings.OutPoint_free(funding_txo); + //bindings.ChannelMonitorUpdate_free(update); We'll need this after 681 return bindings.CResult_NoneChannelMonitorUpdateErrZ_ok(); } @Override public long release_pending_monitor_events() { + synchronized (monitors) { + assert monitors.size() <= 1; + for (Long mon : monitors.values()) { + return bindings.ChannelMonitor_get_and_clear_pending_monitor_events(mon); + } + } return bindings.new_empty_slice_vec(); } }); @@ -52,6 +81,7 @@ public class PeerTest { this.keys_interface = bindings.KeysManager_as_KeysInterface(keys); this.config = bindings.UserConfig_default(); this.chan_manager = bindings.ChannelManager_new(LDKNetwork.LDKNetwork_Bitcoin, fee_estimator, chain_monitor, tx_broadcaster, logger, keys_interface, config, 1); + this.node_id = bindings.ChannelManager_get_our_node_id(chan_manager); this.chan_manager_events = bindings.ChannelManager_as_EventsProvider(chan_manager); this.chan_handler = bindings.ChannelManager_as_ChannelMessageHandler(chan_manager); @@ -64,6 +94,28 @@ public class PeerTest { this.peer_manager = bindings.PeerManager_new(message_handler, bindings.LDKKeysInterface_call_get_node_secret(keys_interface), random_data, logger); } + void connect_block(Block b, Transaction t, int height) { + byte[] header = b.bitcoinSerialize(); + long txn; + if (t != null) + txn = bindings.LDKCVecTempl_C2TupleTempl_usize__Transaction_new( + new long[] {bindings.C2Tuple_usizeTransactionZ_new(1, bindings.new_txpointer_copy_data(t.bitcoinSerialize()))}); + else + txn = bindings.LDKCVecTempl_C2TupleTempl_usize__Transaction_new(new long[0]); + bindings.ChannelManager_block_connected(chan_manager, header, txn, height); + synchronized (monitors) { + for (Long mon : monitors.values()) { + if (t != null) + txn = bindings.LDKCVecTempl_C2TupleTempl_usize__Transaction_new( + new long[] {bindings.C2Tuple_usizeTransactionZ_new(1, bindings.new_txpointer_copy_data(t.bitcoinSerialize()))}); + else + txn = bindings.LDKCVecTempl_C2TupleTempl_usize__Transaction_new(new long[0]); + long ret = bindings.ChannelMonitor_block_connected(mon, header, txn, height, tx_broadcaster, fee_estimator, logger); + bindings.CVec_C2Tuple_TxidCVec_TxOutZZZ_free(ret); + } + } + } + void free() { // Note that we can't rely on finalizer order, so don't bother trying to rely on it here bindings.Logger_free(logger); @@ -79,6 +131,11 @@ public class PeerTest { bindings.RoutingMessageHandler_free(route_handler); //MessageHandler was actually moved into the route_handler!: bindings.MessageHandler_free(message_handler); bindings.PeerManager_free(peer_manager); + synchronized (monitors) { + for (Long mon : monitors.values()) { + bindings.ChannelMonitor_free(mon); + } + } } } @@ -92,7 +149,7 @@ public class PeerTest { assert bindings.LDKCResult_boolPeerHandleErrorZ_result_ok(res); //assert bindings.deref_bool(bindings.LDKCResult_boolPeerHandleErrorZ_get_inner(res)); bindings.CResult_boolPeerHandleErrorZ_free(res); - bindings.free_heap_ptr(arr_vec); + bindings.CVec_u8Z_free(arr_vec); }); thread.start(); list.add(thread); @@ -129,7 +186,7 @@ public class PeerTest { @Override public long hash() { return 1; } }); - long init_vec = bindings.PeerManager_new_outbound_connection(peer1.peer_manager, bindings.ChannelManager_get_our_node_id(peer2.chan_manager), descriptor1.val); + long init_vec = bindings.PeerManager_new_outbound_connection(peer1.peer_manager, peer2.node_id, descriptor1.val); assert(bindings.LDKCResult_CVec_u8ZPeerHandleErrorZ_result_ok(init_vec)); long con_res = bindings.PeerManager_new_inbound_connection(peer2.peer_manager, descriptor2); @@ -140,7 +197,7 @@ public class PeerTest { while (!list.isEmpty()) { list.poll().join(); } - long cc_res = bindings.ChannelManager_create_channel(peer1.chan_manager, bindings.ChannelManager_get_our_node_id(peer2.chan_manager), 10000, 1000, 0, bindings.LDKUserConfig_optional_none()); + long cc_res = bindings.ChannelManager_create_channel(peer1.chan_manager, peer2.node_id, 10000, 1000, 42, 0); assert bindings.LDKCResult_NoneAPIErrorZ_result_ok(cc_res); bindings.CResult_NoneAPIErrorZ_free(cc_res); @@ -152,15 +209,74 @@ public class PeerTest { long events = bindings.LDKEventsProvider_call_get_and_clear_pending_events(peer1.chan_manager_events); bindings.VecOrSliceDef events_arr_info = bindings.LDKCVecTempl_Event_arr_info(events); assert events_arr_info.datalen == 1; + bindings.LDKEvent event = bindings.LDKEvent_ref_from_ptr(events_arr_info.dataptr); + assert event instanceof bindings.LDKEvent.FundingGenerationReady; + assert ((bindings.LDKEvent.FundingGenerationReady)event).channel_value_satoshis == 10000; + assert ((bindings.LDKEvent.FundingGenerationReady)event).user_channel_id == 42; + byte[] funding_spk = bindings.get_u8_slice_bytes(((bindings.LDKEvent.FundingGenerationReady)event).output_script); + assert funding_spk.length == 34 && funding_spk[0] == 0 && funding_spk[1] == 32; // P2WSH + byte[] chan_id = ((bindings.LDKEvent.FundingGenerationReady)event).temporary_channel_id; bindings.CVec_EventZ_free(events); + Transaction funding = new Transaction(NetworkParameters.fromID(NetworkParameters.ID_MAINNET)); + funding.addInput(new TransactionInput(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), funding, new byte[0])); + funding.getInputs().get(0).setWitness(new TransactionWitness(2)); // Make sure we don't complain about lack of witness + funding.getInput(0).getWitness().setPush(0, new byte[] {0x1}); + funding.addOutput(Coin.SATOSHI.multiply(10000), new Script(funding_spk)); + bindings.ChannelManager_funding_transaction_generated(peer1.chan_manager, chan_id, bindings.OutPoint_new(funding.getTxId().getReversedBytes(), (short) 0)); + + bindings.PeerManager_process_events(peer1.peer_manager); + while (!list.isEmpty()) { list.poll().join(); } + bindings.PeerManager_process_events(peer2.peer_manager); + while (!list.isEmpty()) { list.poll().join(); } + + events = bindings.LDKEventsProvider_call_get_and_clear_pending_events(peer1.chan_manager_events); + events_arr_info = bindings.LDKCVecTempl_Event_arr_info(events); + assert events_arr_info.datalen == 1; + event = bindings.LDKEvent_ref_from_ptr(events_arr_info.dataptr); + assert event instanceof bindings.LDKEvent.FundingBroadcastSafe; + bindings.CVec_EventZ_free(events); + + Block b = new Block(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), 2, Sha256Hash.ZERO_HASH, Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{funding})); + peer1.connect_block(b, funding, 1); + peer2.connect_block(b, funding, 1); + + for (int height = 2; height < 10; height++) { + b = new Block(NetworkParameters.fromID(NetworkParameters.ID_MAINNET), 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{funding})); + peer1.connect_block(b, null, height); + peer2.connect_block(b, null, height); + } + + bindings.PeerManager_process_events(peer1.peer_manager); + bindings.PeerManager_process_events(peer2.peer_manager); + while (!list.isEmpty()) { list.poll().join(); } + long peer1_chans = bindings.ChannelManager_list_channels(peer1.chan_manager); long peer2_chans = bindings.ChannelManager_list_channels(peer2.chan_manager); assert bindings.vec_slice_len(peer1_chans) == 1; assert bindings.vec_slice_len(peer2_chans) == 1; - bindings.CVec_ChannelDetailsZ_free(peer1_chans); + long[] peer_1_chan_info = bindings.LDKCVecTempl_ChannelDetails_arr_info(peer1_chans); + assert peer_1_chan_info.length == 1; + assert bindings.ChannelDetails_get_channel_value_satoshis(peer_1_chan_info[0]) == 10000; + assert bindings.ChannelDetails_get_is_live(peer_1_chan_info[0]); + assert Arrays.equals(bindings.ChannelDetails_get_channel_id(peer_1_chan_info[0]), funding.getTxId().getReversedBytes()); + assert Arrays.equals(bindings.ChannelDetails_get_channel_id(bindings.LDKCVecTempl_ChannelDetails_arr_info(peer2_chans)[0]), funding.getTxId().getReversedBytes()); bindings.CVec_ChannelDetailsZ_free(peer2_chans); + byte[] payment_preimage = new byte[32]; + for (int i = 0; i < 32; i++) payment_preimage[i] = (byte) (i ^ 0x0f); + byte[] payment_hash = Sha256Hash.hash(payment_preimage); + long netgraph = bindings.NetGraphMsgHandler_read_locked_graph(peer1.router); + long route = bindings.get_route(peer1.node_id, bindings.LockedNetworkGraph_graph(netgraph), peer2.node_id, peer1_chans, + bindings.LDKCVecTempl_RouteHint_new(new long[0]), 1000, 42, peer1.logger); + bindings.CVec_ChannelDetailsZ_free(peer1_chans); + assert bindings.LDKCResult_RouteLightningErrorZ_result_ok(route); + bindings.LockedNetworkGraph_free(netgraph); + long payment_res = bindings.ChannelManager_send_payment(peer1.chan_manager, bindings.LDKCResult_RouteLightningErrorZ_get_inner(route), payment_hash, new byte[32]); + bindings.CResult_RouteLightningErrorZ_free(route); + assert bindings.LDKCResult_NonePaymentSendFailureZ_result_ok(payment_res); + bindings.CResult_NonePaymentSendFailureZ_free(payment_res); + peer1.free(); peer2.free(); bindings.SocketDescriptor_free(descriptor2);