invoices: accept mpp payments

This commit is contained in:
Joost Jager committed 2019-12-11 16:14:49 +01:00
1 parent 56958493fe
commit b2f43858c3
10 files changed
+1125 -594

No files matched your search

+92
View File
@@ -16,6 +16,8 @@ import (
var (
testTimeout = 5 * time.Second
testTime = time.Date(2018, time.February, 2, 14, 0, 0, 0, time.UTC)
preimage = lntypes.Preimage{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
@@ -59,20 +61,27 @@ var (
type testContext struct {
registry *InvoiceRegistry
clock *testClock
cleanup func()
t *testing.T
}
func newTestContext(t *testing.T) *testContext {
clock := newTestClock(testTime)
cdb, cleanup, err := newDB()
if err != nil {
t.Fatal(err)
}
cdb.Now = clock.now
// Instantiate and start the invoice ctx.registry.
cfg := RegistryConfig{
FinalCltvRejectDelta: testFinalCltvRejectDelta,
HtlcHoldDuration: 30 * time.Second,
Now: clock.now,
TickAfter: clock.tickAfter,
}
registry := NewRegistry(cdb, &cfg)
@@ -84,6 +93,7 @@ func newTestContext(t *testing.T) *testContext {
ctx := testContext{
registry: registry,
clock: clock,
t: t,
cleanup: func() {
registry.Stop()
@@ -683,3 +693,85 @@ func (p *mockPayload) MultiPath() *record.MPP {
func (p *mockPayload) CustomRecords() hop.CustomRecordSet {
return make(hop.CustomRecordSet)
}
// TestSettleMpp tests settling of an invoice with multiple partial payments.
func TestSettleMpp(t *testing.T) {
defer timeout(t)()
ctx := newTestContext(t)
defer ctx.cleanup()
// Add the invoice.
_, err := ctx.registry.AddInvoice(testInvoice, hash)
if err != nil {
t.Fatal(err)
}
mppPayload := &mockPayload{
mpp: record.NewMPP(testInvoiceAmt, [32]byte{}),
}
// Send htlc 1.
hodlChan1 := make(chan interface{}, 1)
event, err := ctx.registry.NotifyExitHopHtlc(
hash, testInvoice.Terms.Value/2,
testHtlcExpiry,
testCurrentHeight, getCircuitKey(10), hodlChan1, mppPayload,
)
if err != nil {
t.Fatal(err)
}
if event != nil {
t.Fatal("expected no direct resolution")
}
// Simulate mpp timeout releasing htlc 1.
ctx.clock.setTime(testTime.Add(30 * time.Second))
hodlEvent := (<-hodlChan1).(HodlEvent)
if hodlEvent.Preimage != nil {
t.Fatal("expected cancel event")
}
// Send htlc 2.
hodlChan2 := make(chan interface{}, 1)
event, err = ctx.registry.NotifyExitHopHtlc(
hash, testInvoice.Terms.Value/2,
testHtlcExpiry,
testCurrentHeight, getCircuitKey(11), hodlChan2, mppPayload,
)
if err != nil {
t.Fatal(err)
}
if event != nil {
t.Fatal("expected no direct resolution")
}
// Send htlc 3.
hodlChan3 := make(chan interface{}, 1)
event, err = ctx.registry.NotifyExitHopHtlc(
hash, testInvoice.Terms.Value/2,
testHtlcExpiry,
testCurrentHeight, getCircuitKey(12), hodlChan3, mppPayload,
)
if err != nil {
t.Fatal(err)
}
if event == nil {
t.Fatal("expected a settle event")
}
// Check that settled amount is equal to the sum of values of the htlcs
// 0 and 1.
inv, err := ctx.registry.LookupInvoice(hash)
if err != nil {
t.Fatal(err)
}
if inv.State != channeldb.ContractSettled {
t.Fatal("expected invoice to be settled")
}
if inv.AmtPaid != testInvoice.Terms.Value {
t.Fatalf("amount incorrect, expected %v but got %v",
testInvoice.Terms.Value, inv.AmtPaid)
}
}