mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-19 20:15:18 +02:00
cnct+htlcswitch+invoices: report circuit key to invoice registry
Currently the invoice registry cannot tell apart the htlcs that pay to an invoice. Because htlcs may also be replayed on startup, it isn't possible to determine the total amount paid to an invoice. This commit is a first step towards fixing that. It reports the circuit keys of htlcs to the invoice registry, which forms the basis for accurate invoice accounting.
This commit is contained in:
@@ -484,14 +484,15 @@ func (i *InvoiceRegistry) checkHtlcParameters(invoice *channeldb.Invoice,
|
||||
// prevent deadlock.
|
||||
func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
|
||||
amtPaid lnwire.MilliSatoshi, expiry uint32, currentHeight int32,
|
||||
hodlChan chan<- interface{}, eob []byte) (*HodlEvent, error) {
|
||||
circuitKey channeldb.CircuitKey, hodlChan chan<- interface{},
|
||||
eob []byte) (*HodlEvent, error) {
|
||||
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
debugLog := func(s string) {
|
||||
log.Debugf("Invoice(%x): %v, amt=%v, expiry=%v",
|
||||
rHash[:], s, amtPaid, expiry)
|
||||
log.Debugf("Invoice(%x): %v, amt=%v, expiry=%v, circuit=%v",
|
||||
rHash[:], s, amtPaid, expiry, circuitKey)
|
||||
}
|
||||
|
||||
// If this isn't a debug invoice, then we'll attempt to settle an
|
||||
|
@@ -64,6 +64,15 @@ func newTestContext(t *testing.T) (*InvoiceRegistry, func()) {
|
||||
}
|
||||
}
|
||||
|
||||
func getCircuitKey(htlcID uint64) channeldb.CircuitKey {
|
||||
return channeldb.CircuitKey{
|
||||
ChanID: lnwire.ShortChannelID{
|
||||
BlockHeight: 1, TxIndex: 2, TxPosition: 3,
|
||||
},
|
||||
HtlcID: htlcID,
|
||||
}
|
||||
}
|
||||
|
||||
// TestSettleInvoice tests settling of an invoice and related notifications.
|
||||
func TestSettleInvoice(t *testing.T) {
|
||||
registry, cleanup := newTestContext(t)
|
||||
@@ -121,7 +130,8 @@ func TestSettleInvoice(t *testing.T) {
|
||||
// Settle invoice with a slightly higher amount.
|
||||
amtPaid := lnwire.MilliSatoshi(100500)
|
||||
_, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -153,10 +163,11 @@ func TestSettleInvoice(t *testing.T) {
|
||||
t.Fatal("no update received")
|
||||
}
|
||||
|
||||
// Try to settle again. We need this idempotent behaviour after a
|
||||
// restart.
|
||||
// Try to settle again with the same htlc id. We need this idempotent
|
||||
// behaviour after a restart.
|
||||
event, err := registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err)
|
||||
@@ -165,12 +176,12 @@ func TestSettleInvoice(t *testing.T) {
|
||||
t.Fatal("expected settle event")
|
||||
}
|
||||
|
||||
// Try to settle again with a higher amount. This payment should also be
|
||||
// accepted, to prevent any change in behaviour for a paid invoice that
|
||||
// may open up a probe vector.
|
||||
// Try to settle again with a new higher-valued htlc. This payment
|
||||
// should also be accepted, to prevent any change in behaviour for a
|
||||
// paid invoice that may open up a probe vector.
|
||||
event, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid+600, testHtlcExpiry, testCurrentHeight,
|
||||
hodlChan, nil,
|
||||
getCircuitKey(1), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err)
|
||||
@@ -183,7 +194,7 @@ func TestSettleInvoice(t *testing.T) {
|
||||
// would have failed if it were the first payment.
|
||||
event, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid-600, testHtlcExpiry, testCurrentHeight,
|
||||
hodlChan, nil,
|
||||
getCircuitKey(2), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err)
|
||||
@@ -306,7 +317,8 @@ func TestCancelInvoice(t *testing.T) {
|
||||
// succeed.
|
||||
hodlChan := make(chan interface{})
|
||||
event, err := registry.NotifyExitHopHtlc(
|
||||
hash, amt, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amt, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal("expected settlement of a canceled invoice to succeed")
|
||||
@@ -382,7 +394,8 @@ func TestHoldInvoice(t *testing.T) {
|
||||
// NotifyExitHopHtlc without a preimage present in the invoice registry
|
||||
// should be possible.
|
||||
event, err := registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
@@ -393,7 +406,8 @@ func TestHoldInvoice(t *testing.T) {
|
||||
|
||||
// Test idempotency.
|
||||
event, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
@@ -406,7 +420,7 @@ func TestHoldInvoice(t *testing.T) {
|
||||
// is a replay.
|
||||
event, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, testHtlcExpiry, testCurrentHeight+10,
|
||||
getCircuitKey(0), hodlChan,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
@@ -420,7 +434,7 @@ func TestHoldInvoice(t *testing.T) {
|
||||
// doesn't track individual htlcs it is accepted.
|
||||
event, err = registry.NotifyExitHopHtlc(
|
||||
hash, amtPaid, 1, testCurrentHeight,
|
||||
getCircuitKey(1), hodlChan,
|
||||
getCircuitKey(1), hodlChan, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
@@ -520,7 +534,8 @@ func TestUnknownInvoice(t *testing.T) {
|
||||
hodlChan := make(chan interface{})
|
||||
amt := lnwire.MilliSatoshi(100000)
|
||||
_, err := registry.NotifyExitHopHtlc(
|
||||
hash, amt, testHtlcExpiry, testCurrentHeight, hodlChan, nil,
|
||||
hash, amt, testHtlcExpiry, testCurrentHeight,
|
||||
getCircuitKey(0), hodlChan, nil,
|
||||
)
|
||||
if err != channeldb.ErrInvoiceNotFound {
|
||||
t.Fatal("expected invoice not found error")
|
||||
|
Reference in New Issue
Block a user