Skip to content

Commit 4707fb6

Browse files
committed
[C#] Update test to LDK 0.0.123 and pay a BOLT12 offer
1 parent 592c64e commit 4707fb6

File tree

1 file changed

+134
-19
lines changed

1 file changed

+134
-19
lines changed

c_sharp/test/src/tests.cs

+134-19
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ static void SimpleConstructionTest() {
2121
}
2222

2323
class TestBroadcaster : BroadcasterInterfaceInterface {
24-
public bool broadcasted = false;
24+
public int broadcasted_len = 0;
2525
public void broadcast_transactions(byte[][] txn) {
2626
Assert(txn.Length == 1, 1);
27-
Assert(txn[0].Length == 42, 2);
28-
broadcasted = true;
27+
broadcasted_len = txn[0].Length;
2928
}
3029
}
3130

@@ -35,7 +34,7 @@ static void SimpleTraitTest() {
3534
byte[][] txn = new byte[1][];
3635
txn[0] = new byte[42];
3736
broadcaster.broadcast_transactions(txn);
38-
Assert(impl.broadcasted == true, 3);
37+
Assert(impl.broadcasted_len == 42, 3);
3938
}
4039

4140
class TestEstimator : FeeEstimatorInterface {
@@ -61,6 +60,7 @@ public ChannelMonitorUpdateStatus persist_new_channel(OutPoint channel_id, Chann
6160
public ChannelMonitorUpdateStatus update_persisted_channel(OutPoint channel_id, ChannelMonitorUpdate update, ChannelMonitor data, MonitorUpdateId update_id) {
6261
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed;
6362
}
63+
public void archive_persisted_channel(OutPoint channel_id) { }
6464
}
6565

6666
class TestEventHandler : EventHandlerInterface {
@@ -77,31 +77,75 @@ static Event get_event(ChannelManager manager) {
7777
return impl.events[0];
7878
}
7979

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+
80113
class Node {
81-
public BroadcasterInterface broadcaster = BroadcasterInterface.new_impl(new TestBroadcaster());
114+
public TestBroadcaster broadcaster = new TestBroadcaster();
82115
public FeeEstimator estimator = FeeEstimator.new_impl(new TestEstimator());
83116
public Logger logger = Logger.new_impl(new TestLogger());
84117
public Persist persister = Persist.new_impl(new TestPersister());
85118
public ChainParameters chain_params = ChainParameters.of(Network.LDKNetwork_Bitcoin, BestBlock.from_network(Network.LDKNetwork_Bitcoin));
86119

120+
public BroadcasterInterface ldk_broadcaster;
87121
public ChainMonitor chain_monitor;
88122
public NetworkGraph graph;
89123
public MultiThreadedLockableScore scorer;
90-
public DefaultRouter router;
124+
public Router router;
91125
public KeysManager keys;
92126
public ChannelManager manager;
127+
public OnionMessenger messenger;
93128

94129
public Node(byte seed) {
95130
byte[] seed_bytes = new byte[32];
96131
for (int i = 0; i < 32; i++) seed_bytes[i] = seed;
97132
keys = KeysManager.of(seed_bytes, 42, 43);
98133

99-
chain_monitor = ChainMonitor.of(Option_FilterZ.none(), broadcaster, logger, estimator, persister);
134+
ldk_broadcaster = BroadcasterInterface.new_impl(broadcaster);
135+
chain_monitor = ChainMonitor.of(Option_FilterZ.none(), ldk_broadcaster, logger, estimator, persister);
100136
graph = NetworkGraph.of(Network.LDKNetwork_Bitcoin, logger);
101137
scorer = MultiThreadedLockableScore.of(ProbabilisticScorer.of(ProbabilisticScoringDecayParameters.with_default(), graph, logger).as_Score());
102-
router = DefaultRouter.of(graph, logger, keys.as_EntropySource(), scorer.as_LockableScore(), ProbabilisticScoringFeeParameters.with_default());
103138

104-
manager = ChannelManager.of(estimator, chain_monitor.as_Watch(), broadcaster, router.as_Router(), logger, keys.as_EntropySource(), keys.as_NodeSigner(), keys.as_SignerProvider(), UserConfig.with_default(), chain_params, 42);
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());
105149
}
106150
}
107151

@@ -110,29 +154,38 @@ static void NodeTest() {
110154
Node node_b = new Node(2);
111155

112156
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();
113158
Init init_msg = Init.of(init_features, Option_CVec_ThirtyTwoBytesZZ.none(), Option_SocketAddressZ.none());
114159
node_a.manager.as_ChannelMessageHandler().peer_connected(node_b.manager.get_our_node_id(), init_msg, false);
115160
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);
116163

117-
Result_ThirtyTwoBytesAPIErrorZ res = node_a.manager.create_channel(node_b.manager.get_our_node_id(), 100000, 42, new UInt128(43), Option_ThirtyTwoBytesZ.none(), null);
164+
Result_ChannelIdAPIErrorZ res = node_a.manager.create_channel(node_b.manager.get_our_node_id(), 100000, 42, new UInt128(43), null, null);
118165
Assert(res.is_ok(), 4);
119166

120167
MessageSendEvent[] msgs = node_a.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
121168
Assert(msgs.Length == 1, 5);
122169
Assert(msgs[0] is MessageSendEvent.MessageSendEvent_SendOpenChannel, 6);
123170
node_b.manager.as_ChannelMessageHandler().handle_open_channel(node_a.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendOpenChannel) msgs[0]).msg);
124171

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+
125178
MessageSendEvent[] response_msgs = node_b.manager.as_MessageSendEventsProvider().get_and_clear_pending_msg_events();
126-
Assert(response_msgs.Length == 1, 7);
127-
Assert(response_msgs[0] is MessageSendEvent.MessageSendEvent_SendAcceptChannel, 8);
179+
Assert(response_msgs.Length == 1, 9);
180+
Assert(response_msgs[0] is MessageSendEvent.MessageSendEvent_SendAcceptChannel, 10);
128181
node_a.manager.as_ChannelMessageHandler().handle_accept_channel(node_b.manager.get_our_node_id(), ((MessageSendEvent.MessageSendEvent_SendAcceptChannel) response_msgs[0]).msg);
129182

130183
Event funding_ready = get_event(node_a.manager);
131-
Assert(funding_ready is Event.Event_FundingGenerationReady, 9);
184+
Assert(funding_ready is Event.Event_FundingGenerationReady, 11);
132185

133186
// We could use funding_transaction_generated here, but test batching
134-
TwoTuple_ThirtyTwoBytesPublicKeyZ[] channel = new TwoTuple_ThirtyTwoBytesPublicKeyZ[1];
135-
channel[0] = TwoTuple_ThirtyTwoBytesPublicKeyZ.of(((Event.Event_FundingGenerationReady) funding_ready).temporary_channel_id, ((Event.Event_FundingGenerationReady) funding_ready).counterparty_node_id);
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);
136189

137190
// Hand-crafted transaction which has a dummy witness and can pay to our script
138191
byte[] transaction = new byte[99];
@@ -185,17 +238,17 @@ static void NodeTest() {
185238
transaction[46] = 255;
186239
transaction[47] = 255;
187240
transaction[48] = 1;
188-
transaction[49] = 34;
189-
transaction[50] = 2;
190-
transaction[51] = 0;
241+
transaction[49] = 160;
242+
transaction[50] = 134;
243+
transaction[51] = 1;
191244
transaction[52] = 0;
192245
transaction[53] = 0;
193246
transaction[54] = 0;
194247
transaction[55] = 0;
195248
transaction[56] = 0;
196249
transaction[57] = 34;
197250

198-
Assert(((Event.Event_FundingGenerationReady) funding_ready).output_script.Length == 34, 10);
251+
Assert(((Event.Event_FundingGenerationReady) funding_ready).output_script.Length == 34, 12);
199252
for (int i = 0; i < 34; i++) {
200253
transaction[58 + i] = ((Event.Event_FundingGenerationReady) funding_ready).output_script[i];
201254
}
@@ -209,6 +262,68 @@ static void NodeTest() {
209262
transaction[98] = 0;
210263

211264
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);
212327
}
213328

214329
static void Main(string[] args) {

0 commit comments

Comments
 (0)