Skip to content

Commit 117ce51

Browse files
authored
Cover missing C# FFI validation paths (payjoin#1423)
2 parents 43ca1fc + 2d73756 commit 117ce51

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

payjoin-ffi/csharp/IntegrationTests.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ public void TestFfiValidation()
379379
});
380380

381381
var validTxid = new string('0', 64);
382-
Assert.Throws<InputPairException.FfiValidation>(() =>
382+
var amountOutOfRange = Assert.Throws<InputPairException.FfiValidation>(() =>
383383
{
384384
var txin = new PlainTxIn(
385385
new PlainOutPoint(validTxid, 0),
@@ -394,10 +394,11 @@ public void TestFfiValidation()
394394
);
395395
new InputPair(txin, psbtIn, null);
396396
});
397+
Assert.IsType<FfiValidationException.AmountOutOfRange>(amountOutOfRange.v1);
397398

398399
var hugeScript = new byte[10_001];
399400
Array.Fill(hugeScript, (byte)0x51);
400-
Assert.Throws<InputPairException.FfiValidation>(() =>
401+
var scriptTooLarge = Assert.Throws<InputPairException.FfiValidation>(() =>
401402
{
402403
var txin = new PlainTxIn(
403404
new PlainOutPoint(validTxid, 0),
@@ -412,8 +413,9 @@ public void TestFfiValidation()
412413
);
413414
new InputPair(txin, psbtIn, null);
414415
});
416+
Assert.IsType<FfiValidationException.ScriptTooLarge>(scriptTooLarge.v1);
415417

416-
Assert.Throws<InputPairException.FfiValidation>(() =>
418+
var weightOutOfRange = Assert.Throws<InputPairException.FfiValidation>(() =>
417419
{
418420
var txin = new PlainTxIn(
419421
new PlainOutPoint(validTxid, 0),
@@ -428,6 +430,7 @@ public void TestFfiValidation()
428430
);
429431
new InputPair(txin, psbtIn, new PlainWeight(0));
430432
});
433+
Assert.IsType<FfiValidationException.WeightOutOfRange>(weightOutOfRange.v1);
431434

432435
Assert.NotNull(_services);
433436
var directory = _services.DirectoryUrl();
@@ -440,12 +443,13 @@ public void TestFfiValidation()
440443
using var receiver = receiveTransition.Save(recvPersister);
441444
using var pjUri = receiver.PjUri();
442445

443-
var psbt = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=";
446+
var psbt = PayjoinMethods.OriginalPsbt();
444447

445-
Assert.Throws<SenderInputException.FfiValidation>(() =>
448+
var feeRateOutOfRange = Assert.Throws<SenderInputException.FfiValidation>(() =>
446449
{
447450
new SenderBuilder(psbt, pjUri).BuildRecommended(ulong.MaxValue);
448451
});
452+
Assert.IsType<FfiValidationException.FeeRateOutOfRange>(feeRateOutOfRange.v1);
449453

450454
Assert.Throws<FfiValidationException.AmountOutOfRange>(() =>
451455
{

payjoin-ffi/csharp/UnitTests.cs

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public void SenderPersistence()
168168
var uri = receiver.PjUri();
169169

170170
var senderPersister = new InMemorySenderPersister();
171-
var psbt = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=";
171+
var psbt = PayjoinMethods.OriginalPsbt();
172172

173173
var withReplyKey = new SenderBuilder(psbt, uri)
174174
.BuildRecommended(1000)
@@ -210,7 +210,7 @@ public async Task SenderPersistenceAsync()
210210
var uri = receiver.PjUri();
211211

212212
var senderPersister = new InMemorySenderPersisterAsync();
213-
var psbt = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=";
213+
var psbt = PayjoinMethods.OriginalPsbt();
214214

215215
var withReplyKey = await new SenderBuilder(psbt, uri)
216216
.BuildRecommended(1000)
@@ -237,6 +237,16 @@ public class ValidationTests
237237
0x00, 0x01, 0x00, 0x03,
238238
};
239239

240+
private static PjUri CreateV2PjUri()
241+
{
242+
var ohttpKeys = OhttpKeys.Decode(OhttpKeysData);
243+
var persister = new InMemoryReceiverPersister();
244+
using var builder = new ReceiverBuilder("2MuyMrZHkbHbfjudmKUy45dU4P17pjG2szK", "https://example.com", ohttpKeys);
245+
using var transition = builder.Build();
246+
using var receiver = transition.Save(persister);
247+
return receiver.PjUri();
248+
}
249+
240250
[Fact]
241251
public void ReceiverBuilderRejectsBadAddress()
242252
{
@@ -263,4 +273,93 @@ public void InputPairRejectsInvalidOutpoint()
263273
new InputPair(txin, psbtIn, null);
264274
});
265275
}
276+
277+
[Fact]
278+
public void SenderBuilderRejectsBadPsbt()
279+
{
280+
using var parsed = Uri.Parse("bitcoin:tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4?pj=https://example.com/pj");
281+
using var uri = parsed.CheckPjSupported();
282+
283+
var ex = Assert.Throws<SenderInputException.Psbt>(() =>
284+
{
285+
new SenderBuilder("not-a-psbt", uri);
286+
});
287+
288+
Assert.IsType<PsbtParseException.InvalidPsbt>(ex.v1);
289+
}
290+
291+
[Fact]
292+
public void ReceiverBuilderRejectsAmountOverflow()
293+
{
294+
var ohttpKeys = OhttpKeys.Decode(OhttpKeysData);
295+
using var builder = new ReceiverBuilder(
296+
"tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4",
297+
"https://example.com",
298+
ohttpKeys);
299+
300+
Assert.Throws<FfiValidationException.AmountOutOfRange>(() =>
301+
{
302+
builder.WithAmount(21_000_000UL * 100_000_000UL + 1);
303+
});
304+
}
305+
306+
[Fact]
307+
public void ReceiverBuilderRejectsExpirationOverflow()
308+
{
309+
var ohttpKeys = OhttpKeys.Decode(OhttpKeysData);
310+
using var builder = new ReceiverBuilder(
311+
"tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4",
312+
"https://example.com",
313+
ohttpKeys);
314+
315+
Assert.Throws<FfiValidationException.ExpirationOutOfRange>(() =>
316+
{
317+
builder.WithExpiration((ulong)uint.MaxValue + 1);
318+
});
319+
}
320+
321+
[Fact]
322+
public void SenderBuilderWithAdditionalFeeRejectsFeeContributionOverflow()
323+
{
324+
using var uri = CreateV2PjUri();
325+
var psbt = PayjoinMethods.OriginalPsbt();
326+
using var builder = new SenderBuilder(psbt, uri);
327+
328+
var ex = Assert.Throws<SenderInputException.FfiValidation>(() =>
329+
{
330+
builder.BuildWithAdditionalFee(21_000_000UL * 100_000_000UL + 1, null, 1000, false);
331+
});
332+
333+
Assert.IsType<FfiValidationException.AmountOutOfRange>(ex.v1);
334+
}
335+
336+
[Fact]
337+
public void SenderBuilderWithAdditionalFeeRejectsFeeRateOverflow()
338+
{
339+
using var uri = CreateV2PjUri();
340+
var psbt = PayjoinMethods.OriginalPsbt();
341+
using var builder = new SenderBuilder(psbt, uri);
342+
343+
var ex = Assert.Throws<SenderInputException.FfiValidation>(() =>
344+
{
345+
builder.BuildWithAdditionalFee(1, null, ulong.MaxValue, false);
346+
});
347+
348+
Assert.IsType<FfiValidationException.FeeRateOutOfRange>(ex.v1);
349+
}
350+
351+
[Fact]
352+
public void SenderBuilderNonIncentivizingRejectsFeeRateOverflow()
353+
{
354+
using var uri = CreateV2PjUri();
355+
var psbt = PayjoinMethods.OriginalPsbt();
356+
using var builder = new SenderBuilder(psbt, uri);
357+
358+
var ex = Assert.Throws<SenderInputException.FfiValidation>(() =>
359+
{
360+
builder.BuildNonIncentivizing(ulong.MaxValue);
361+
});
362+
363+
Assert.IsType<FfiValidationException.FeeRateOutOfRange>(ex.v1);
364+
}
266365
}

0 commit comments

Comments
 (0)