channeldb: split settleHodlInvoice logic in the UpdateInvoice method

This commit is contained in:
positiveblue 2023-02-01 06:15:32 -08:00
parent a3f6d5c97e
commit cbaec4382a
No known key found for this signature in database
GPG Key ID: 4FFF2510928804DC
2 changed files with 86 additions and 3 deletions

View File

@ -1896,6 +1896,12 @@ func (d *DB) updateInvoice(hash *lntypes.Hash, refSetID *invpkg.SetID, invoices,
switch update.UpdateType {
case invpkg.CancelHTLCsUpdate:
return d.cancelHTLCs(invoices, invoiceNum, &invoice, update)
case invpkg.SettleHodlInvoiceUpdate:
return d.settleHodlInvoice(
invoices, settleIndex, invoiceNum, &invoice, hash,
update.State,
)
}
var (
@ -2219,6 +2225,84 @@ func (d *DB) cancelHTLCs(invoices kvdb.RwBucket, invoiceNum []byte,
return invoice, nil
}
// settleHodlInvoice marks a hodl invoice as settled.
//
// NOTE: Currently it is not possible to have HODL AMP invoices.
func (d *DB) settleHodlInvoice(invoices, settleIndex kvdb.RwBucket,
invoiceNum []byte, invoice *invpkg.Invoice, hash *lntypes.Hash,
update *invpkg.InvoiceStateUpdateDesc) (*invpkg.Invoice, error) {
if !invoice.HodlInvoice {
return nil, fmt.Errorf("unable to settle hodl invoice: %v is "+
"not a hodl invoice", invoice.AddIndex)
}
// TODO(positiveblue): because NewState can only be ContractSettled we
// can remove it from the API and set it here directly.
switch {
case update == nil:
fallthrough
case update.NewState != invpkg.ContractSettled:
return nil, fmt.Errorf("unable to settle hodl invoice: "+
"not valid InvoiceUpdateDesc.State: %v", update)
case update.Preimage == nil:
return nil, fmt.Errorf("unable to settle hodl invoice: " +
"preimage is nil")
}
// TODO(positiveblue): create a invoice.CanSettleHodlInvoice func.
newState, err := updateInvoiceState(invoice, hash, *update)
if err != nil {
return nil, err
}
if newState == nil || *newState != invpkg.ContractSettled {
return nil, fmt.Errorf("unable to settle hodl invoice: "+
"new computed state is not settled: %s", newState)
}
invoice.State = invpkg.ContractSettled
timestamp := d.clock.Now()
err = setSettleMetaFields(
settleIndex, invoiceNum, invoice, timestamp, nil,
)
if err != nil {
return nil, err
}
// TODO(positiveblue): this logic can be further simplified.
var amtPaid lnwire.MilliSatoshi
for _, htlc := range invoice.Htlcs {
_, err := updateHtlc(
timestamp, htlc, invpkg.ContractSettled, nil,
)
if err != nil {
return nil, err
}
if htlc.State == invpkg.HtlcStateSettled {
amtPaid += htlc.Amt
}
}
invoice.AmtPaid = amtPaid
// Reserialize and update invoice.
var buf bytes.Buffer
if err := serializeInvoice(&buf, invoice); err != nil {
return nil, err
}
if err := invoices.Put(invoiceNum, buf.Bytes()); err != nil {
return nil, err
}
return invoice, nil
}
// updateInvoiceState validates and processes an invoice state update. The new
// state to transition to is returned, so the caller is able to select exactly
// how the invoice state is updated.

View File

@ -1231,9 +1231,7 @@ func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error {
i.Lock()
defer i.Unlock()
updateInvoice := func(invoice *Invoice) (
*InvoiceUpdateDesc, error) {
updateInvoice := func(invoice *Invoice) (*InvoiceUpdateDesc, error) {
switch invoice.State {
case ContractOpen:
return nil, ErrInvoiceStillOpen
@ -1246,6 +1244,7 @@ func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error {
}
return &InvoiceUpdateDesc{
UpdateType: SettleHodlInvoiceUpdate,
State: &InvoiceStateUpdateDesc{
NewState: ContractSettled,
Preimage: &preimage,