multi: break invoice depenency on channeldb

Now that we have the new package `lnd/channeldb/models` we can invert the
depenency between `channeldb` and `invoices`.

- Move all the invoice related types and errors to the
`invoices` package.

- Ensure that all the packages dealing with invoices use the types and
  interfaces defined in the `invoices` package.

- Implement the InvoiceDB interface (defined in `lnd/invoices`) in
  channeldb.

- Add new mock for InterfaceDB.

- `InvoiceRegistery` tests are now in its own subpacakge (they need to
  import both invoices & channeldb). This is temporary until we can
  decouple them.
This commit is contained in:
positiveblue committed 2023-01-16 07:31:09 -08:00
1 parent 383cb40f8d
commit 5ff5225245
26 files changed
+2839 -2253

No files matched your search

+42 -43
View File
@@ -5,8 +5,6 @@ import (
"errors"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
@@ -16,7 +14,7 @@ import (
// update to be carried out.
type invoiceUpdateCtx struct {
hash lntypes.Hash
circuitKey models.CircuitKey
circuitKey CircuitKey
amtPaid lnwire.MilliSatoshi
expiry uint32
currentHeight int32
@@ -29,16 +27,18 @@ type invoiceUpdateCtx struct {
// invoiceRef returns an identifier that can be used to lookup or update the
// invoice this HTLC is targeting.
func (i *invoiceUpdateCtx) invoiceRef() channeldb.InvoiceRef {
func (i *invoiceUpdateCtx) invoiceRef() InvoiceRef {
switch {
case i.amp != nil && i.mpp != nil:
payAddr := i.mpp.PaymentAddr()
return channeldb.InvoiceRefByAddr(payAddr)
return InvoiceRefByAddr(payAddr)
case i.mpp != nil:
payAddr := i.mpp.PaymentAddr()
return channeldb.InvoiceRefByHashAndAddr(i.hash, payAddr)
return InvoiceRefByHashAndAddr(i.hash, payAddr)
default:
return channeldb.InvoiceRefByHash(i.hash)
return InvoiceRefByHash(i.hash)
}
}
@@ -95,20 +95,20 @@ func (i invoiceUpdateCtx) acceptRes(outcome acceptResolutionResult) *htlcAcceptR
// updateInvoice is a callback for DB.UpdateInvoice that contains the invoice
// settlement logic. It returns a hltc resolution that indicates what the
// outcome of the update was.
func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) (
*channeldb.InvoiceUpdateDesc, HtlcResolution, error) {
func updateInvoice(ctx *invoiceUpdateCtx, inv *Invoice) (
*InvoiceUpdateDesc, HtlcResolution, error) {
// Don't update the invoice when this is a replayed htlc.
htlc, ok := inv.Htlcs[ctx.circuitKey]
if ok {
switch htlc.State {
case channeldb.HtlcStateCanceled:
case HtlcStateCanceled:
return nil, ctx.failRes(ResultReplayToCanceled), nil
case channeldb.HtlcStateAccepted:
case HtlcStateAccepted:
return nil, ctx.acceptRes(resultReplayToAccepted), nil
case channeldb.HtlcStateSettled:
case HtlcStateSettled:
pre := inv.Terms.PaymentPreimage
// Terms.PaymentPreimage will be nil for AMP invoices.
@@ -139,8 +139,7 @@ func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) (
// updateMpp is a callback for DB.UpdateInvoice that contains the invoice
// settlement logic for mpp payments.
func updateMpp(ctx *invoiceUpdateCtx,
inv *channeldb.Invoice) (*channeldb.InvoiceUpdateDesc,
func updateMpp(ctx *invoiceUpdateCtx, inv *Invoice) (*InvoiceUpdateDesc,
HtlcResolution, error) {
// Reject HTLCs to AMP invoices if they are missing an AMP payload, and
@@ -160,7 +159,7 @@ func updateMpp(ctx *invoiceUpdateCtx,
setID := ctx.setID()
// Start building the accept descriptor.
acceptDesc := &channeldb.HtlcAcceptDesc{
acceptDesc := &HtlcAcceptDesc{
Amt: ctx.amtPaid,
Expiry: ctx.expiry,
AcceptHeight: ctx.currentHeight,
@@ -169,7 +168,7 @@ func updateMpp(ctx *invoiceUpdateCtx,
}
if ctx.amp != nil {
acceptDesc.AMP = &channeldb.InvoiceHtlcAMPData{
acceptDesc.AMP = &InvoiceHtlcAMPData{
Record: *ctx.amp,
Hash: ctx.hash,
Preimage: nil,
@@ -180,7 +179,7 @@ func updateMpp(ctx *invoiceUpdateCtx,
// non-mpp payments that are accepted even after the invoice is settled.
// Because non-mpp payments don't have a payment address, this is needed
// to thwart probing.
if inv.State != channeldb.ContractOpen {
if inv.State != ContractOpen {
return nil, ctx.failRes(ResultInvoiceNotOpen), nil
}
@@ -200,7 +199,7 @@ func updateMpp(ctx *invoiceUpdateCtx,
return nil, ctx.failRes(ResultHtlcSetTotalTooLow), nil
}
htlcSet := inv.HTLCSet(setID, channeldb.HtlcStateAccepted)
htlcSet := inv.HTLCSet(setID, HtlcStateAccepted)
// Check whether total amt matches other htlcs in the set.
var newSetTotal lnwire.MilliSatoshi
@@ -229,16 +228,16 @@ func updateMpp(ctx *invoiceUpdateCtx,
return nil, ctx.failRes(ResultExpiryTooSoon), nil
}
if setID != nil && *setID == channeldb.BlankPayAddr {
if setID != nil && *setID == BlankPayAddr {
return nil, ctx.failRes(ResultAmpError), nil
}
// Record HTLC in the invoice database.
newHtlcs := map[models.CircuitKey]*channeldb.HtlcAcceptDesc{
newHtlcs := map[CircuitKey]*HtlcAcceptDesc{
ctx.circuitKey: acceptDesc,
}
update := channeldb.InvoiceUpdateDesc{
update := InvoiceUpdateDesc{
AddHtlcs: newHtlcs,
}
@@ -251,23 +250,23 @@ func updateMpp(ctx *invoiceUpdateCtx,
// Check to see if we can settle or this is an hold invoice and
// we need to wait for the preimage.
if inv.HodlInvoice {
update.State = &channeldb.InvoiceStateUpdateDesc{
NewState: channeldb.ContractAccepted,
update.State = &InvoiceStateUpdateDesc{
NewState: ContractAccepted,
SetID: setID,
}
return &update, ctx.acceptRes(resultAccepted), nil
}
var (
htlcPreimages map[models.CircuitKey]lntypes.Preimage
htlcPreimages map[CircuitKey]lntypes.Preimage
htlcPreimage lntypes.Preimage
)
if ctx.amp != nil {
var failRes *HtlcFailResolution
htlcPreimages, failRes = reconstructAMPPreimages(ctx, htlcSet)
if failRes != nil {
update.State = &channeldb.InvoiceStateUpdateDesc{
NewState: channeldb.ContractCanceled,
update.State = &InvoiceStateUpdateDesc{
NewState: ContractCanceled,
SetID: setID,
}
return &update, failRes, nil
@@ -280,8 +279,8 @@ func updateMpp(ctx *invoiceUpdateCtx,
htlcPreimage = *inv.Terms.PaymentPreimage
}
update.State = &channeldb.InvoiceStateUpdateDesc{
NewState: channeldb.ContractSettled,
update.State = &InvoiceStateUpdateDesc{
NewState: ContractSettled,
Preimage: inv.Terms.PaymentPreimage,
HTLCPreimages: htlcPreimages,
SetID: setID,
@@ -291,10 +290,10 @@ func updateMpp(ctx *invoiceUpdateCtx,
}
// HTLCSet is a map of CircuitKey to InvoiceHTLC.
type HTLCSet = map[models.CircuitKey]*channeldb.InvoiceHTLC
type HTLCSet = map[CircuitKey]*InvoiceHTLC
// HTLCPreimages is a map of CircuitKey to preimage.
type HTLCPreimages = map[models.CircuitKey]lntypes.Preimage
type HTLCPreimages = map[CircuitKey]lntypes.Preimage
// reconstructAMPPreimages reconstructs the root seed for an AMP HTLC set and
// verifies that all derived child hashes match the payment hashes of the HTLCs
@@ -317,7 +316,7 @@ func reconstructAMPPreimages(ctx *invoiceUpdateCtx,
// Next, construct an index mapping the position in childDescs to a
// circuit key for all preexisting HTLCs.
indexToCircuitKey := make(map[int]models.CircuitKey)
indexToCircuitKey := make(map[int]CircuitKey)
// Add the child descriptor for each HTLC in the HTLC set, recording
// it's position within the slice.
@@ -351,7 +350,7 @@ func reconstructAMPPreimages(ctx *invoiceUpdateCtx,
// Finally, construct the map of learned preimages indexed by circuit
// key, so that they can be persisted along with each HTLC when updating
// the invoice.
htlcPreimages := make(map[models.CircuitKey]lntypes.Preimage)
htlcPreimages := make(map[CircuitKey]lntypes.Preimage)
htlcPreimages[ctx.circuitKey] = children[0].Preimage
for idx, child := range children[1:] {
circuitKey := indexToCircuitKey[idx]
@@ -368,11 +367,11 @@ func reconstructAMPPreimages(ctx *invoiceUpdateCtx,
// send payments and any invoices we created in the past that are valid and
// still had the optional mpp bit set.
func updateLegacy(ctx *invoiceUpdateCtx,
inv *channeldb.Invoice) (*channeldb.InvoiceUpdateDesc, HtlcResolution, error) {
inv *Invoice) (*InvoiceUpdateDesc, HtlcResolution, error) {
// If the invoice is already canceled, there is no further
// checking to do.
if inv.State == channeldb.ContractCanceled {
if inv.State == ContractCanceled {
return nil, ctx.failRes(ResultInvoiceAlreadyCanceled), nil
}
@@ -402,7 +401,7 @@ func updateLegacy(ctx *invoiceUpdateCtx,
// Don't allow settling the invoice with an old style
// htlc if we are already in the process of gathering an
// mpp set.
for _, htlc := range inv.HTLCSet(nil, channeldb.HtlcStateAccepted) {
for _, htlc := range inv.HTLCSet(nil, HtlcStateAccepted) {
if htlc.MppTotalAmt > 0 {
return nil, ctx.failRes(ResultMppInProgress), nil
}
@@ -418,7 +417,7 @@ func updateLegacy(ctx *invoiceUpdateCtx,
}
// Record HTLC in the invoice database.
newHtlcs := map[models.CircuitKey]*channeldb.HtlcAcceptDesc{
newHtlcs := map[CircuitKey]*HtlcAcceptDesc{
ctx.circuitKey: {
Amt: ctx.amtPaid,
Expiry: ctx.expiry,
@@ -427,17 +426,17 @@ func updateLegacy(ctx *invoiceUpdateCtx,
},
}
update := channeldb.InvoiceUpdateDesc{
update := InvoiceUpdateDesc{
AddHtlcs: newHtlcs,
}
// Don't update invoice state if we are accepting a duplicate payment.
// We do accept or settle the HTLC.
switch inv.State {
case channeldb.ContractAccepted:
case ContractAccepted:
return &update, ctx.acceptRes(resultDuplicateToAccepted), nil
case channeldb.ContractSettled:
case ContractSettled:
return &update, ctx.settleRes(
*inv.Terms.PaymentPreimage, ResultDuplicateToSettled,
), nil
@@ -446,15 +445,15 @@ func updateLegacy(ctx *invoiceUpdateCtx,
// Check to see if we can settle or this is an hold invoice and we need
// to wait for the preimage.
if inv.HodlInvoice {
update.State = &channeldb.InvoiceStateUpdateDesc{
NewState: channeldb.ContractAccepted,
update.State = &InvoiceStateUpdateDesc{
NewState: ContractAccepted,
}
return &update, ctx.acceptRes(resultAccepted), nil
}
update.State = &channeldb.InvoiceStateUpdateDesc{
NewState: channeldb.ContractSettled,
update.State = &InvoiceStateUpdateDesc{
NewState: ContractSettled,
Preimage: inv.Terms.PaymentPreimage,
}