Skip to content

Commit 9e43343

Browse files
committed
[C#] Test BOLT 12 Invoice[Request] builders with their references
1 parent 7ebd5df commit 9e43343

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

c_sharp/test/src/tests.cs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4+
using System.Threading;
5+
using System.Runtime.InteropServices;
46
using org.ldk.enums;
57
using org.ldk.util;
68
using org.ldk.structs;
@@ -350,12 +352,107 @@ static void Bolt12ParseTest() {
350352
Assert(offer.to_str() == offerStr, 109);
351353
}
352354

355+
static Offer BuildOffer(Nonce nonce, KeysManager keys) {
356+
Result_PublicKeyNoneZ id_res = keys.as_NodeSigner().get_node_id(Recipient.LDKRecipient_Node);
357+
byte[] node_id = ((Result_PublicKeyNoneZ.Result_PublicKeyNoneZ_OK)id_res).res;
358+
ExpandedKey inb_key = ExpandedKey.of(keys.as_NodeSigner().get_inbound_payment_key_material());
359+
OfferWithDerivedMetadataBuilder builder = OfferWithDerivedMetadataBuilder.deriving_signing_pubkey(node_id, inb_key, nonce);
360+
Result_OfferBolt12SemanticErrorZ res = builder.build();
361+
return ((Result_OfferBolt12SemanticErrorZ.Result_OfferBolt12SemanticErrorZ_OK) res).res;
362+
}
363+
364+
static InvoiceRequestWithDerivedPayerIdBuilder InvReqBuilderFromOffer(Offer offer, KeysManager keys) {
365+
ExpandedKey inb_key = ExpandedKey.of(keys.as_NodeSigner().get_inbound_payment_key_material());
366+
Nonce nonce = Nonce.from_entropy_source(keys.as_EntropySource());
367+
Result_InvoiceRequestWithDerivedPayerIdBuilderBolt12SemanticErrorZ builder_res =
368+
offer.request_invoice_deriving_payer_id(inb_key, nonce, new byte[32]);
369+
InvoiceRequestWithDerivedPayerIdBuilder builder =
370+
((Result_InvoiceRequestWithDerivedPayerIdBuilderBolt12SemanticErrorZ.Result_InvoiceRequestWithDerivedPayerIdBuilderBolt12SemanticErrorZ_OK)builder_res).res;
371+
return builder;
372+
}
373+
374+
static InvoiceRequest BuildInvReq(InvoiceRequestWithDerivedPayerIdBuilder builder) {
375+
Result_InvoiceRequestBolt12SemanticErrorZ res = builder.build_and_sign();
376+
return ((Result_InvoiceRequestBolt12SemanticErrorZ.Result_InvoiceRequestBolt12SemanticErrorZ_OK)res).res;
377+
}
378+
379+
static InvoiceWithDerivedSigningPubkeyBuilder InvBuilderFromInvReq(Nonce receiver_nonce, InvoiceRequest invreq, KeysManager keys) {
380+
ExpandedKey inb_key = ExpandedKey.of(keys.as_NodeSigner().get_inbound_payment_key_material());
381+
Result_VerifiedInvoiceRequestNoneZ verified_res = invreq.verify_using_recipient_data(receiver_nonce, inb_key);
382+
VerifiedInvoiceRequest verified_invreq =
383+
((Result_VerifiedInvoiceRequestNoneZ.Result_VerifiedInvoiceRequestNoneZ_OK)verified_res).res;
384+
Result_InvoiceWithDerivedSigningPubkeyBuilderBolt12SemanticErrorZ builder_res =
385+
verified_invreq.respond_using_derived_keys(new BlindedPaymentPath[0], new byte[32]);
386+
InvoiceWithDerivedSigningPubkeyBuilder builder =
387+
((Result_InvoiceWithDerivedSigningPubkeyBuilderBolt12SemanticErrorZ.Result_InvoiceWithDerivedSigningPubkeyBuilderBolt12SemanticErrorZ_OK)builder_res).res;
388+
return builder;
389+
}
390+
391+
static InvoiceRequestWithDerivedPayerIdBuilder InvReqBuilder(Nonce receiver_nonce, KeysManager payer, KeysManager recipient) {
392+
// Under the hood, InvoiceRequestWithDerivedPayerIdBuilder holds a reference to some
393+
// fields in the Offer. Thus, we build an Offer here, then return only the builder,
394+
// hoping the GC will cause us to free the Offer and use-after-free.
395+
Offer offer = BuildOffer(receiver_nonce, payer);
396+
return InvReqBuilderFromOffer(offer, recipient);
397+
}
398+
399+
static InvoiceWithDerivedSigningPubkeyBuilder InvBuilderFromInvReqBuilder(Nonce receiver_nonce, InvoiceRequestWithDerivedPayerIdBuilder builder, KeysManager payer, KeysManager recipient) {
400+
// Same as above, but for the Invoice itself
401+
InvoiceRequest invreq = BuildInvReq(builder);
402+
return InvBuilderFromInvReq(receiver_nonce, invreq, recipient);
403+
}
404+
405+
static void Bolt12RespondTest() {
406+
// Build an Invoice out of an Offer, step by step. We do each step in its own function
407+
// to give the background GC a chance to free things out from under us.
408+
KeysManager sender = KeysManager.of(new byte[32], 42, 42);
409+
byte[] receiver_keys = new byte[32];
410+
receiver_keys[10] = 42;
411+
KeysManager receiver = KeysManager.of(receiver_keys, 42, 42);
412+
413+
// Run the GC between each step to see if the reference the builders hold to the
414+
// original Offer/InvoiceRequest is freed out from under us before building.
415+
Nonce receiver_nonce = Nonce.from_entropy_source(receiver.as_EntropySource());
416+
InvoiceRequestWithDerivedPayerIdBuilder invreq_builder = InvReqBuilder(receiver_nonce, sender, receiver);
417+
System.GC.Collect();
418+
GC.WaitForPendingFinalizers();
419+
InvoiceWithDerivedSigningPubkeyBuilder inv_builder = InvBuilderFromInvReqBuilder(receiver_nonce, invreq_builder, sender, receiver);
420+
System.GC.Collect();
421+
GC.WaitForPendingFinalizers();
422+
Result_Bolt12InvoiceBolt12SemanticErrorZ inv_res = inv_builder.build_and_sign();
423+
Assert(inv_res.is_ok(), 200);
424+
}
425+
426+
static void GCLoop() {
427+
while (Thread.CurrentThread.IsAlive) {
428+
System.GC.Collect();
429+
GC.WaitForPendingFinalizers();
430+
try {
431+
Thread.Sleep(new TimeSpan(1));
432+
} catch (ThreadInterruptedException _) {
433+
break;
434+
}
435+
}
436+
}
437+
353438
static void Main(string[] args) {
439+
Thread gc_thread = null;
440+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
441+
// No idea why this dies on macOS, but it does, so disable it.
442+
gc_thread = new Thread(GCLoop);
443+
gc_thread.Start();
444+
}
445+
354446
SimpleConstructionTest();
355447
SimpleTraitTest();
356448
NodeTest();
357449
Bolt12ParseTest();
358450

451+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
452+
gc_thread.Interrupt();
453+
gc_thread.Join();
454+
}
455+
359456
Console.WriteLine("\n\nTESTS PASSED\n\n");
360457
System.GC.Collect();
361458
GC.WaitForPendingFinalizers();

0 commit comments

Comments
 (0)