Fix returning traits in trait calls, move towards clone on return
[ldk-java] / src / test / java / org / ldk / HumanObjectPeerTest.java
index 8e7e42f12d63975c1a292ae28b720ca82e77b313..26f20d34b5e70b8d088c2ebe8574061d0d847fac 100644 (file)
@@ -17,10 +17,99 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 
 class HumanObjectPeerTestInstance {
     class Peer {
+        KeysInterface manual_keysif(KeysInterface underlying_if) {
+            return KeysInterface.new_impl(new KeysInterface.KeysInterfaceInterface() {
+                @Override
+                public byte[] get_node_secret() {
+                    return underlying_if.get_node_secret();
+                }
+
+                @Override
+                public byte[] get_destination_script() {
+                    return underlying_if.get_destination_script();
+                }
+
+                @Override
+                public byte[] get_shutdown_pubkey() {
+                    return underlying_if.get_shutdown_pubkey();
+                }
+
+                @Override
+                public ChannelKeys get_channel_keys(boolean inbound, long channel_value_satoshis) {
+                    ChannelKeys underlying_ck = underlying_if.get_channel_keys(inbound, channel_value_satoshis);
+                    ChannelKeys.ChannelKeysInterface cki = new ChannelKeys.ChannelKeysInterface() {
+                        @Override
+                        public byte[] get_per_commitment_point(long idx) {
+                            return underlying_ck.get_per_commitment_point(idx);
+                        }
+
+                        @Override
+                        public byte[] release_commitment_secret(long idx) {
+                            return underlying_ck.release_commitment_secret(idx);
+                        }
+
+                        @Override
+                        public TwoTuple<Long, Long> key_derivation_params() {
+                            return new TwoTuple<Long, Long>((long)0, (long)1);
+                        }
+
+                        @Override
+                        public Result_C2Tuple_SignatureCVec_SignatureZZNoneZ sign_counterparty_commitment(int feerate_per_kw, byte[] commitment_tx, PreCalculatedTxCreationKeys keys, HTLCOutputInCommitment[] htlcs) {
+                            return underlying_ck.sign_counterparty_commitment(feerate_per_kw, commitment_tx, keys, htlcs);
+                        }
+
+                        @Override
+                        public Result_SignatureNoneZ sign_holder_commitment(HolderCommitmentTransaction holder_commitment_tx) {
+                            return underlying_ck.sign_holder_commitment(holder_commitment_tx);
+                        }
+
+                        @Override
+                        public Result_CVec_SignatureZNoneZ sign_holder_commitment_htlc_transactions(HolderCommitmentTransaction holder_commitment_tx) {
+                            return underlying_ck.sign_holder_commitment_htlc_transactions(holder_commitment_tx);
+                        }
+
+                        @Override
+                        public Result_SignatureNoneZ sign_justice_transaction(byte[] justice_tx, long input, long amount, byte[] per_commitment_key, HTLCOutputInCommitment htlc) {
+                            return underlying_ck.sign_justice_transaction(justice_tx, input, amount, per_commitment_key, htlc);
+                        }
+
+                        @Override
+                        public Result_SignatureNoneZ sign_counterparty_htlc_transaction(byte[] htlc_tx, long input, long amount, byte[] per_commitment_point, HTLCOutputInCommitment htlc) {
+                            return underlying_ck.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc);
+                        }
+
+                        @Override
+                        public Result_SignatureNoneZ sign_closing_transaction(byte[] closing_tx) {
+                            return underlying_ck.sign_closing_transaction(closing_tx);
+                        }
+
+                        @Override
+                        public Result_SignatureNoneZ sign_channel_announcement(UnsignedChannelAnnouncement msg) {
+                            return underlying_ck.sign_channel_announcement(msg);
+                        }
+
+                        @Override
+                        public void on_accept(ChannelPublicKeys channel_points, short counterparty_selected_contest_delay, short holder_selected_contest_delay) {
+                            underlying_ck.on_accept(channel_points, counterparty_selected_contest_delay, holder_selected_contest_delay);
+                        }
+                    };
+                    ChannelKeys resp = ChannelKeys.new_impl(cki, underlying_ck.get_pubkeys());
+                    must_free_objs.add(new WeakReference<>(cki));
+                    must_free_objs.add(new WeakReference<>(resp));
+                    must_free_objs.add(new WeakReference<>(underlying_ck));
+                    return resp;
+                }
+
+                @Override
+                public byte[] get_secure_random_bytes() {
+                    return underlying_if.get_secure_random_bytes();
+                }
+            });
+        }
+
         final Logger logger;
         final FeeEstimator fee_estimator;
         final BroadcasterInterface tx_broadcaster;
-        final KeysManager keys;
         final KeysInterface keys_interface;
         final ChannelManager chan_manager;
         final EventsProvider chan_manager_events;
@@ -28,16 +117,16 @@ class HumanObjectPeerTestInstance {
         final PeerManager peer_manager;
         final HashMap<String, ChannelMonitor> monitors; // Wow I forgot just how terrible Java is - we can't put a byte array here.
         byte[] node_id;
-        final LinkedList<org.ldk.structs.Transaction> broadcast_set = new LinkedList<>();
+        final LinkedList<byte[]> broadcast_set = new LinkedList<>();
 
-        Peer(byte seed) {
-            logger = new Logger((String arg) -> System.out.println(seed + ": " + arg));
-            fee_estimator = new FeeEstimator((confirmation_target -> 253));
-            tx_broadcaster = new BroadcasterInterface(tx -> {
+        Peer(byte seed, boolean use_km_wrapper) {
+            logger = Logger.new_impl((String arg) -> System.out.println(seed + ": " + arg));
+            fee_estimator = FeeEstimator.new_impl((confirmation_target -> 253));
+            tx_broadcaster = BroadcasterInterface.new_impl(tx -> {
                 broadcast_set.add(tx);
             });
             this.monitors = new HashMap<>();
-            Watch chain_monitor = new Watch(new Watch.WatchInterface() {
+            Watch chain_monitor = Watch.new_impl(new Watch.WatchInterface() {
                 public Result_NoneChannelMonitorUpdateErrZ watch_channel(OutPoint funding_txo, ChannelMonitor monitor) {
                     synchronized (monitors) {
                         assert monitors.put(Arrays.toString(funding_txo.get_txid()), monitor) == null;
@@ -71,9 +160,14 @@ class HumanObjectPeerTestInstance {
             for (byte i = 0; i < 32; i++) {
                 key_seed[i] = (byte) (i ^ seed);
             }
-            this.keys = KeysManager.constructor_new(key_seed, LDKNetwork.LDKNetwork_Bitcoin, System.currentTimeMillis() / 1000, (int) (System.currentTimeMillis() * 1000) & 0xffffffff);
-            this.keys_interface = keys.as_KeysInterface();
-            this.chan_manager = ChannelManager.constructor_new(LDKNetwork.LDKNetwork_Bitcoin, new FeeEstimator(confirmation_target -> 0), chain_monitor, tx_broadcaster, logger, keys.as_KeysInterface(), UserConfig.constructor_default(), 1);
+            if (use_km_wrapper) {
+                KeysManager underlying = KeysManager.constructor_new(key_seed, LDKNetwork.LDKNetwork_Bitcoin, System.currentTimeMillis() / 1000, (int) (System.currentTimeMillis() * 1000) & 0xffffffff);
+                this.keys_interface = manual_keysif(underlying.as_KeysInterface());
+            } else {
+                KeysManager keys = KeysManager.constructor_new(key_seed, LDKNetwork.LDKNetwork_Bitcoin, System.currentTimeMillis() / 1000, (int) (System.currentTimeMillis() * 1000) & 0xffffffff);
+                this.keys_interface = keys.as_KeysInterface();
+            }
+            this.chan_manager = ChannelManager.constructor_new(LDKNetwork.LDKNetwork_Bitcoin, FeeEstimator.new_impl(confirmation_target -> 0), chain_monitor, tx_broadcaster, logger, this.keys_interface, UserConfig.constructor_default(), 1);
             this.node_id = chan_manager.get_our_node_id();
             this.chan_manager_events = chan_manager.as_EventsProvider();
             this.router = NetGraphMsgHandler.constructor_new(null, logger);
@@ -86,22 +180,23 @@ class HumanObjectPeerTestInstance {
             System.gc();
         }
 
-        void connect_block(Block b, int height) {
+        TwoTuple<byte[], TxOut[]>[] connect_block(Block b, int height) {
             byte[] header = Arrays.copyOfRange(b.bitcoinSerialize(), 0, 80);
-            TwoTuple<Long, org.ldk.structs.Transaction>[] txn;
+            TwoTuple<Long, byte[]>[] txn;
             if (b.hasTransactions()) {
                 assert b.getTransactions().size() == 1;
-                TwoTuple<Long, org.ldk.structs.Transaction> txp = new TwoTuple<>((long) 1, new org.ldk.structs.Transaction(b.getTransactions().get(0).bitcoinSerialize()));
+                TwoTuple<Long, byte[]> txp = new TwoTuple<>((long) 1, b.getTransactions().get(0).bitcoinSerialize());
                 txn = new TwoTuple[]{txp};
             } else
                 txn = new TwoTuple[0];
             chan_manager.block_connected(header, txn, height);
             synchronized (monitors) {
+                assert monitors.size() == 1;
                 for (ChannelMonitor mon : monitors.values()) {
-                    TwoTuple<byte[], TxOut[]>[] ret = mon.block_connected(header, txn, height, tx_broadcaster, fee_estimator, logger);
-                    assert ret.length == 0;
+                    return mon.block_connected(header, txn, height, tx_broadcaster, fee_estimator, logger);
                 }
             }
+            return null;
         }
 
         Route get_route(byte[] dest_node, ChannelDetails[] our_chans) {
@@ -145,10 +240,10 @@ class HumanObjectPeerTestInstance {
         }
     }
 
-    void do_test_message_handler(boolean nice_close) throws InterruptedException {
+    void do_test_message_handler(boolean nice_close, boolean use_km_wrapper) throws InterruptedException {
         GcCheck obj = new GcCheck();
-        Peer peer1 = new Peer((byte) 1);
-        Peer peer2 = new Peer((byte) 2);
+        Peer peer1 = new Peer((byte) 1, use_km_wrapper);
+        Peer peer2 = new Peer((byte) 2, use_km_wrapper);
 
         ConcurrentLinkedQueue<Thread> list = new ConcurrentLinkedQueue<Thread>();
         LongHolder descriptor1 = new LongHolder();
@@ -227,13 +322,13 @@ class HumanObjectPeerTestInstance {
         assert ((Event.FundingBroadcastSafe) events[0]).user_channel_id == 42;
 
         Block b = new Block(bitcoinj_net, 2, Sha256Hash.ZERO_HASH, Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{funding}));
-        peer1.connect_block(b, 1);
-        peer2.connect_block(b, 1);
+        assert peer1.connect_block(b, 1).length == 0;
+        assert peer2.connect_block(b, 1).length == 0;
 
         for (int height = 2; height < 10; height++) {
             b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[0]));
-            peer1.connect_block(b, height);
-            peer2.connect_block(b, height);
+            assert peer1.connect_block(b, height).length == 0;
+            assert peer2.connect_block(b, height).length == 0;
         }
 
         peer1.peer_manager.process_events();
@@ -316,8 +411,13 @@ class HumanObjectPeerTestInstance {
             assert peer1.broadcast_set.size() == 1;
             assert peer2.broadcast_set.size() == 0;
 
-            //b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{new Transaction(bitcoinj_net, peer1.broadcast_set.getFirst())}));
-            //peer2.connect_block(b, 1);
+            Transaction tx = new Transaction(bitcoinj_net, peer1.broadcast_set.getFirst());
+            b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0,
+                    Arrays.asList(new Transaction[]{tx}));
+            TwoTuple<byte[], TxOut[]>[] watch_outputs =  peer2.connect_block(b, 1);
+            assert watch_outputs.length == 1;
+            assert Arrays.equals(watch_outputs[0].a, tx.getTxId().getReversedBytes());
+            assert watch_outputs[0].b.length == 1;
         }
 
         bindings.SocketDescriptor_free(descriptor2);
@@ -326,10 +426,9 @@ class HumanObjectPeerTestInstance {
 
 }
 public class HumanObjectPeerTest {
-    @Test
-    public void test_message_handler_force_close() throws InterruptedException {
+    void do_test(boolean nice_close, boolean use_km_wrapper) throws InterruptedException {
         HumanObjectPeerTestInstance instance = new HumanObjectPeerTestInstance();
-        instance.do_test_message_handler(false);
+        instance.do_test_message_handler(nice_close, use_km_wrapper);
         while (!instance.gc_ran) {
             System.gc();
             System.runFinalization();
@@ -338,14 +437,19 @@ public class HumanObjectPeerTest {
             assert o.get() == null;
     }
     @Test
+    public void test_message_handler_force_close() throws InterruptedException {
+        do_test(false, false);
+    }
+    @Test
     public void test_message_handler_nice_close() throws InterruptedException {
-        HumanObjectPeerTestInstance instance = new HumanObjectPeerTestInstance();
-        instance.do_test_message_handler(true);
-        while (!instance.gc_ran) {
-            System.gc();
-            System.runFinalization();
-        }
-        for (WeakReference<Object> o : instance.must_free_objs)
-            assert o.get() == null;
+        do_test(true, false);
+    }
+    @Test
+    public void test_message_handler_nice_close_wrapper() throws InterruptedException {
+        do_test(true, true);
+    }
+    @Test
+    public void test_message_handler_force_close_wrapper() throws InterruptedException {
+        do_test(false, true);
     }
 }