[Java] Print error stack trace when tests fail
[ldk-java] / c_sharp / test / src / tests.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using org.ldk.enums;
5 using org.ldk.util;
6 using org.ldk.structs;
7
8 namespace tests {
9         static class Tests {
10                 static void Assert(bool a, int assertion) {
11                         if (!a) {
12                                 Console.WriteLine("Assertion " + assertion + " failed at");
13                                 Console.WriteLine(new StackTrace().ToString());
14                                 Environment.Exit(45);
15                         }
16                 }
17
18                 static void SimpleConstructionTest() {
19                         Ping ping = Ping.of(42, 43);
20                         Assert(ping.get_ponglen() == 42, 0);
21                 }
22
23                 class TestBroadcaster : BroadcasterInterfaceInterface {
24                         public int broadcasted_len = 0;
25                         public void broadcast_transactions(byte[][] txn) {
26                                 Assert(txn.Length == 1, 1);
27                                 broadcasted_len = txn[0].Length;
28                         }
29                 }
30
31                 static void SimpleTraitTest() {
32                         TestBroadcaster impl = new TestBroadcaster();
33                         BroadcasterInterface broadcaster = BroadcasterInterface.new_impl(impl);
34                         byte[][] txn = new byte[1][];
35                         txn[0] = new byte[42];
36                         broadcaster.broadcast_transactions(txn);
37                         Assert(impl.broadcasted_len == 42, 3);
38                 }
39
40                 class TestEstimator : FeeEstimatorInterface {
41                         public int get_est_sat_per_1000_weight(ConfirmationTarget confirmation_target) {
42                                 if (confirmation_target == ConfirmationTarget.LDKConfirmationTarget_MinAllowedNonAnchorChannelRemoteFee) {
43                                         return 253;
44                                 } else {
45                                         return 300;
46                                 }
47                         }
48                 }
49
50                 class TestLogger : LoggerInterface {
51                         public void log(Record record) {
52                                 Console.WriteLine(record.get_module_path() + ":" + record.get_line() + " " + record.get_args());
53                         }
54                 }
55
56                 class TestPersister : PersistInterface {
57                         public ChannelMonitorUpdateStatus persist_new_channel(OutPoint channel_id, ChannelMonitor data, MonitorUpdateId update_id) {
58                                 return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed;
59                         }
60                         public ChannelMonitorUpdateStatus update_persisted_channel(OutPoint channel_id, ChannelMonitorUpdate update, ChannelMonitor data, MonitorUpdateId update_id) {
61                                 return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed;
62                         }
63                         public void archive_persisted_channel(OutPoint channel_id) { }
64                 }
65
66                 class TestEventHandler : EventHandlerInterface {
67                         public List<Event> events = new List<Event>();
68                         public void handle_event(Event ev) {
69                                 events.Add(ev);
70                         }
71                 }
72                 static Event get_event(ChannelManager manager) {
73                         TestEventHandler impl = new TestEventHandler();
74                         org.ldk.structs.EventHandler handler = org.ldk.structs.EventHandler.new_impl(impl);
75                         manager.as_EventsProvider().process_pending_events(handler);
76                         Assert(impl.events.Count == 1, 100);
77                         return impl.events[0];
78                 }
79
80                 class TestRouter : RouterInterface, MessageRouterInterface {
81                         DefaultRouter inner;
82                         EntropySource entropy;
83                         public TestRouter(DefaultRouter inner, EntropySource entropy) {
84                                 this.inner = inner;
85                                 this.entropy = entropy;
86                         }
87                         public Result_RouteLightningErrorZ find_route(byte[] payer, RouteParameters param, ChannelDetails[] chans, InFlightHtlcs htlcs) {
88                                 return inner.as_Router().find_route(payer, param, chans, htlcs);
89                         }
90                         public Result_RouteLightningErrorZ find_route_with_id(byte[] payer, RouteParameters param, ChannelDetails[] chans, InFlightHtlcs htlcs, byte[] payment_hash, byte[] payment_id) {
91                                 return inner.as_Router().find_route_with_id(payer, param, chans, htlcs, payment_hash, payment_id);
92                         }
93                         public Result_CVec_C2Tuple_BlindedPayInfoBlindedPathZZNoneZ create_blinded_payment_paths(byte[] recipient, ChannelDetails[] first_hops, ReceiveTlvs tlvs, long amount_msats) {
94                                 Result_C2Tuple_BlindedPayInfoBlindedPathZNoneZ info_path = UtilMethods.BlindedPath_one_hop_for_payment(recipient, tlvs, 40, entropy);
95                                 TwoTuple_BlindedPayInfoBlindedPathZ hop = ((Result_C2Tuple_BlindedPayInfoBlindedPathZNoneZ.Result_C2Tuple_BlindedPayInfoBlindedPathZNoneZ_OK)info_path).res;
96                                 TwoTuple_BlindedPayInfoBlindedPathZ[] hops = new TwoTuple_BlindedPayInfoBlindedPathZ[1];
97                                 hops[0] = hop;
98                                 return Result_CVec_C2Tuple_BlindedPayInfoBlindedPathZZNoneZ.ok(hops);
99                         }
100
101                         public Result_OnionMessagePathNoneZ find_path(byte[] sender, byte[][] peers, Destination dest) {
102                                 return inner.as_MessageRouter().find_path(sender, peers, dest);
103                         }
104                         public Result_CVec_BlindedPathZNoneZ create_blinded_paths(byte[] recipient, byte[][] peers) {
105                                 Result_BlindedPathNoneZ path = BlindedPath.one_hop_for_message(recipient, entropy);
106                                 Assert(path.is_ok(), 2);
107                                 BlindedPath[] paths = new BlindedPath[1];
108                                 paths[0] = ((Result_BlindedPathNoneZ.Result_BlindedPathNoneZ_OK)path).res;
109                                 return Result_CVec_BlindedPathZNoneZ.ok(paths);
110                         }
111                 }
112
113                 class Node {
114                         public TestBroadcaster broadcaster = new TestBroadcaster();
115                         public FeeEstimator estimator = FeeEstimator.new_impl(new TestEstimator());
116                         public Logger logger = Logger.new_impl(new TestLogger());
117                         public Persist persister = Persist.new_impl(new TestPersister());
118                         public ChainParameters chain_params = ChainParameters.of(Network.LDKNetwork_Bitcoin, BestBlock.from_network(Network.LDKNetwork_Bitcoin));
119
120                         public BroadcasterInterface ldk_broadcaster;
121                         public ChainMonitor chain_monitor;
122                         public NetworkGraph graph;
123                         public MultiThreadedLockableScore scorer;
124                         public Router router;
125                         public KeysManager keys;
126                         public ChannelManager manager;
127                         public OnionMessenger messenger;
128
129                         public Node(byte seed) {
130                                 byte[] seed_bytes = new byte[32];
131                                 for (int i = 0; i < 32; i++) seed_bytes[i] = seed;
132                                 keys = KeysManager.of(seed_bytes, 42, 43);
133
134                                 ldk_broadcaster = BroadcasterInterface.new_impl(broadcaster);
135                                 chain_monitor = ChainMonitor.of(Option_FilterZ.none(), ldk_broadcaster, logger, estimator, persister);
136                                 graph = NetworkGraph.of(Network.LDKNetwork_Bitcoin, logger);
137                                 scorer = MultiThreadedLockableScore.of(ProbabilisticScorer.of(ProbabilisticScoringDecayParameters.with_default(), graph, logger).as_Score());
138
139                                 DefaultRouter router_impl = DefaultRouter.of(graph, logger, keys.as_EntropySource(), scorer.as_LockableScore(), ProbabilisticScoringFeeParameters.with_default());
140                                 TestRouter router_wrapper = new TestRouter(router_impl, keys.as_EntropySource());
141                                 router = Router.new_impl(router_wrapper, router_wrapper);
142
143                                 UserConfig config = UserConfig.with_default();
144                                 config.set_manually_accept_inbound_channels(true);
145
146                                 manager = ChannelManager.of(estimator, chain_monitor.as_Watch(), ldk_broadcaster, router, logger, keys.as_EntropySource(), keys.as_NodeSigner(), keys.as_SignerProvider(), config, chain_params, 42);
147
148                                 messenger = OnionMessenger.of(keys.as_EntropySource(), keys.as_NodeSigner(), logger, manager.as_NodeIdLookUp(), MessageRouter.new_impl(router_wrapper), manager.as_OffersMessageHandler(), IgnoringMessageHandler.of().as_CustomOnionMessageHandler());
149                         }
150                 }
151
152                 static void NodeTest() {
153                         Node node_a = new Node(1);
154                         Node node_b = new Node(2);
155
156                         InitFeatures init_features = node_a.manager.as_ChannelMessageHandler().provided_init_features(node_b.manager.get_our_node_id());
157                         init_features.set_onion_messages_optional();
158                         Init init_msg = Init.of(init_features, Option_CVec_ThirtyTwoBytesZZ.none(), Option_SocketAddressZ.none());
159                         node_a.manager.as_ChannelMessageHandler().peer_connected(node_b.manager.get_our_node_id(), init_msg, false);
160                         node_b.manager.as_ChannelMessageHandler().peer_connected(node_a.manager.get_our_node_id(), init_msg, false);
161                         node_a.messenger.as_OnionMessageHandler().peer_connected(node_b.manager.get_our_node_id(), init_msg, false);
162                         node_b.messenger.as_OnionMessageHandler().peer_connected(node_a.manager.get_our_node_id(), init_msg, false);
163
164                         Result_ChannelIdAPIErrorZ res = node_a.manager.create_channel(node_b.manager.get_our_node_id(), 100000, 42, new UInt128(43), null, null);
165                         Assert(res.is_ok(), 4);
166
167                         MessageSendEvent[] msgs = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
168                         Assert(msgs.Length == 1, 5);
169                         Assert(msgs[0] is MessageSendEvent.MessageSendEvent_SendOpenChannel, 6);
170                         node_b.manager.as_ChannelMessageHandler().handle_open_channel(node_a.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendOpenChannel) msgs[0]).msg);
171
172                         Event inbound_chan = get_event(node_b.manager);
173                         Assert(inbound_chan is Event.Event_OpenChannelRequest, 7);
174                         Event.Event_OpenChannelRequest chan_request = (Event.Event_OpenChannelRequest)inbound_chan;
175                         Result_NoneAPIErrorZ accept_res = node_b.manager.accept_inbound_channel_from_trusted_peer_0conf(chan_request.temporary_channel_id, chan_request.counterparty_node_id, new UInt128(42));
176                         Assert(accept_res.is_ok(), 8);
177
178                         MessageSendEvent[] response_msgs = node_b.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
179                         Assert(response_msgs.Length == 1, 9);
180                         Assert(response_msgs[0] is MessageSendEvent.MessageSendEvent_SendAcceptChannel, 10);
181                         node_a.manager.as_ChannelMessageHandler().handle_accept_channel(node_b.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendAcceptChannel) response_msgs[0]).msg);
182
183                         Event funding_ready = get_event(node_a.manager);
184                         Assert(funding_ready is Event.Event_FundingGenerationReady, 11);
185
186                         // We could use funding_transaction_generated here, but test batching
187                         TwoTuple_ChannelIdPublicKeyZ[] channel = new TwoTuple_ChannelIdPublicKeyZ[1];
188                         channel[0] = TwoTuple_ChannelIdPublicKeyZ.of(((Event.Event_FundingGenerationReady) funding_ready).temporary_channel_id, ((Event.Event_FundingGenerationReady) funding_ready).counterparty_node_id);
189
190                         // Hand-crafted transaction which has a dummy witness and can pay to our script
191                         byte[] transaction = new byte[99];
192                         transaction[0] = 2;
193                         transaction[1] = 0;
194                         transaction[2] = 0;
195                         transaction[3] = 0;
196                         transaction[4] = 0;
197                         transaction[5] = 1;
198                         transaction[6] = 1;
199                         transaction[7] = 66;
200                         transaction[8] = 66;
201                         transaction[9] = 66;
202                         transaction[10] = 66;
203                         transaction[11] = 66;
204                         transaction[12] = 66;
205                         transaction[13] = 66;
206                         transaction[14] = 66;
207                         transaction[15] = 66;
208                         transaction[16] = 66;
209                         transaction[17] = 66;
210                         transaction[18] = 66;
211                         transaction[19] = 66;
212                         transaction[20] = 66;
213                         transaction[21] = 66;
214                         transaction[22] = 66;
215                         transaction[23] = 66;
216                         transaction[24] = 66;
217                         transaction[25] = 66;
218                         transaction[26] = 66;
219                         transaction[27] = 66;
220                         transaction[28] = 66;
221                         transaction[29] = 66;
222                         transaction[30] = 66;
223                         transaction[31] = 66;
224                         transaction[32] = 66;
225                         transaction[33] = 66;
226                         transaction[34] = 66;
227                         transaction[35] = 66;
228                         transaction[36] = 66;
229                         transaction[37] = 66;
230                         transaction[38] = 66;
231                         transaction[39] = 18;
232                         transaction[40] = 0;
233                         transaction[41] = 0;
234                         transaction[42] = 0;
235                         transaction[43] = 0;
236                         transaction[44] = 253;
237                         transaction[45] = 255;
238                         transaction[46] = 255;
239                         transaction[47] = 255;
240                         transaction[48] = 1;
241                         transaction[49] = 160;
242                         transaction[50] = 134;
243                         transaction[51] = 1;
244                         transaction[52] = 0;
245                         transaction[53] = 0;
246                         transaction[54] = 0;
247                         transaction[55] = 0;
248                         transaction[56] = 0;
249                         transaction[57] = 34;
250
251                         Assert(((Event.Event_FundingGenerationReady) funding_ready).output_script.Length == 34, 12);
252                         for (int i = 0; i < 34; i++) {
253                                 transaction[58 + i] = ((Event.Event_FundingGenerationReady) funding_ready).output_script[i];
254                         }
255
256                         transaction[92] = 1;
257                         transaction[93] = 1;
258                         transaction[94] = 1;
259                         transaction[95] = 0;
260                         transaction[96] = 0;
261                         transaction[97] = 0;
262                         transaction[98] = 0;
263
264                         node_a.manager.batch_funding_transaction_generated(channel, transaction);
265
266                         MessageSendEvent[] funding_msg = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
267                         Assert(funding_msg.Length == 1, 13);
268                         Assert(funding_msg[0] is MessageSendEvent.MessageSendEvent_SendFundingCreated, 14);
269                         node_b.manager.as_ChannelMessageHandler().handle_funding_created(node_a.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendFundingCreated) funding_msg[0]).msg);
270
271                         Event bs_chan_pending = get_event(node_b.manager);
272                         Assert(bs_chan_pending is Event.Event_ChannelPending, 15);
273
274                         MessageSendEvent[] signed_ready_msgs = node_b.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
275                         Assert(signed_ready_msgs.Length == 2, 16);
276                         Assert(signed_ready_msgs[0] is MessageSendEvent.MessageSendEvent_SendFundingSigned, 17);
277                         node_a.manager.as_ChannelMessageHandler().handle_funding_signed(node_b.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendFundingSigned) signed_ready_msgs[0]).msg);
278                         Assert(node_a.broadcaster.broadcasted_len == 99, 18);
279
280                         Event as_chan_pending = get_event(node_a.manager);
281                         Assert(as_chan_pending is Event.Event_ChannelPending, 19);
282
283                         MessageSendEvent[] as_ready = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
284                         Assert(as_ready.Length == 1, 20);
285                         Assert(as_ready[0] is MessageSendEvent.MessageSendEvent_SendChannelReady, 21);
286
287                         Assert(signed_ready_msgs[1] is MessageSendEvent.MessageSendEvent_SendChannelReady, 22);
288                         node_a.manager.as_ChannelMessageHandler().handle_channel_ready(node_b.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendChannelReady) signed_ready_msgs[1]).msg);
289
290                         MessageSendEvent[] as_chan_update = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
291                         Assert(as_chan_update.Length == 1, 23);
292                         Assert(as_chan_update[0] is MessageSendEvent.MessageSendEvent_SendChannelUpdate, 24);
293
294                         node_b.manager.as_ChannelMessageHandler().handle_channel_ready(node_a.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendChannelReady) as_ready[0]).msg);
295
296                         Event as_chan_ready = get_event(node_a.manager);
297                         Assert(as_chan_ready is Event.Event_ChannelReady, 25);
298
299                         Event bs_chan_ready = get_event(node_b.manager);
300                         Assert(bs_chan_ready is Event.Event_ChannelReady, 26);
301
302                         MessageSendEvent[] bs_chan_update = node_b.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
303                         Assert(bs_chan_update.Length == 1, 27);
304                         Assert(bs_chan_update[0] is MessageSendEvent.MessageSendEvent_SendChannelUpdate, 28);
305
306                         // Now that we have a channel, pay using a BOLT12 offer!
307
308                         Result_OfferWithDerivedMetadataBuilderBolt12SemanticErrorZ builder_res = node_b.manager.create_offer_builder();
309                         Assert(builder_res.is_ok(), 29);
310                         Result_OfferBolt12SemanticErrorZ offer_res = ((Result_OfferWithDerivedMetadataBuilderBolt12SemanticErrorZ.Result_OfferWithDerivedMetadataBuilderBolt12SemanticErrorZ_OK)builder_res).res.build();
311                         Assert(offer_res.is_ok(), 30);
312                         Offer offer = ((Result_OfferBolt12SemanticErrorZ.Result_OfferBolt12SemanticErrorZ_OK)offer_res).res;
313
314                         Result_NoneBolt12SemanticErrorZ pay_res = node_a.manager.pay_for_offer(offer, Option_u64Z.none(), Option_u64Z.some(42000), Option_StrZ.none(), new byte[32], Retry.attempts(0), Option_u64Z.none());
315                         Assert(pay_res.is_ok(), 31);
316
317                         OnionMessage as_invreq = node_a.messenger.as_OnionMessageHandler().next_onion_message_for_peer(node_b.manager.get_our_node_id());
318                         node_b.messenger.as_OnionMessageHandler().handle_onion_message(node_a.manager.get_our_node_id(), as_invreq);
319
320                         OnionMessage bs_inv = node_b.messenger.as_OnionMessageHandler().next_onion_message_for_peer(node_a.manager.get_our_node_id());
321                         node_a.messenger.as_OnionMessageHandler().handle_onion_message(node_b.manager.get_our_node_id(), bs_inv);
322
323                         // At this point node_a will generate a commitment update for node_b, which we check exists but don't bother to handle:
324                         MessageSendEvent[] as_commit = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
325                         Assert(as_commit.Length == 1, 32);
326                         Assert(as_commit[0] is MessageSendEvent.MessageSendEvent_UpdateHTLCs, 33);
327                 }
328
329                 static void Main(string[] args) {
330                         SimpleConstructionTest();
331                         SimpleTraitTest();
332                         NodeTest();
333
334                         Console.WriteLine("\n\nTESTS PASSED\n\n");
335                         System.GC.Collect();
336                         GC.WaitForPendingFinalizers();
337                 }
338         }
339 }