channeldb: clean updateInvoice func

All the updates type are now catched in a switch statement, we can
delete the rest of the body of this function + add a default path for
not matched flows.
This commit is contained in:
positiveblue 2023-02-23 06:53:24 -08:00
parent 6ff6c45a6b
commit 65fc8d72c6
No known key found for this signature in database
GPG key ID: 4FFF2510928804DC

View file

@ -1913,250 +1913,11 @@ func (d *DB) updateInvoice(hash *lntypes.Hash, refSetID *invpkg.SetID, invoices,
return d.cancelInvoice(
invoices, invoiceNum, &invoice, hash, update.State,
)
default:
return nil, fmt.Errorf("unknown update type: %s",
update.UpdateType)
}
var (
setID *[32]byte
)
// We can either get the set ID from the main state update (if the
// state is changing), or via the hint passed in returned by the update
// call back.
if update.State != nil {
setID = update.State.SetID
}
now := d.clock.Now()
invoiceIsAMP := invoiceCopy.IsAMP()
// Process add actions from update descriptor.
htlcsAmpUpdate := make(map[invpkg.SetID]map[models.CircuitKey]*invpkg.InvoiceHTLC) //nolint:lll
for key, htlcUpdate := range update.AddHtlcs {
if _, exists := invoice.Htlcs[key]; exists {
return nil, fmt.Errorf("duplicate add of htlc %v", key)
}
// Force caller to supply htlc without custom records in a
// consistent way.
if htlcUpdate.CustomRecords == nil {
return nil, errors.New("nil custom records map")
}
// If a newly added HTLC has an associated set id, use it to
// index this invoice in the set id index. An error is returned
// if we find the index already points to a different invoice.
var setID [32]byte
if htlcUpdate.AMP != nil {
setID = htlcUpdate.AMP.Record.SetID()
setIDInvNum := setIDIndex.Get(setID[:])
if setIDInvNum == nil {
err = setIDIndex.Put(setID[:], invoiceNum)
if err != nil {
return nil, err
}
} else if !bytes.Equal(setIDInvNum, invoiceNum) {
err = invpkg.ErrDuplicateSetID{SetID: setID}
return nil, err
}
}
htlc := &invpkg.InvoiceHTLC{
Amt: htlcUpdate.Amt,
MppTotalAmt: htlcUpdate.MppTotalAmt,
Expiry: htlcUpdate.Expiry,
AcceptHeight: uint32(htlcUpdate.AcceptHeight),
AcceptTime: now,
State: invpkg.HtlcStateAccepted,
CustomRecords: htlcUpdate.CustomRecords,
AMP: htlcUpdate.AMP.Copy(),
}
invoice.Htlcs[key] = htlc
// Collect the set of new HTLCs so we can write them properly
// below, but only if this is an AMP invoice.
if invoiceIsAMP {
updateHtlcsAmp(
&invoice, htlcsAmpUpdate, htlc, setID, key,
)
}
}
// At this point, the set of accepted HTLCs should be fully
// populated with added HTLCs or removed of canceled ones. Update
// invoice state if the update descriptor indicates an invoice state
// change, which depends on having an accurate view of the accepted
// HTLCs.
if update.State != nil {
newState, err := updateInvoiceState(
&invoice, hash, *update.State,
)
if err != nil {
return nil, err
}
// If this isn't an AMP invoice, then we'll go ahead and update
// the invoice state directly here. For AMP invoices, we
// instead will keep the top-level invoice open, and instead
// update the state of each _htlc set_ instead. However, we'll
// allow the invoice to transition to the cancelled state
// regardless.
if !invoiceIsAMP || *newState == invpkg.ContractCanceled {
invoice.State = *newState
}
// If this is a non-AMP invoice, then the state can eventually
// go to ContractSettled, so we pass in nil value as part of
// setSettleMetaFields.
isSettled := update.State.NewState == invpkg.ContractSettled
if !invoiceIsAMP && isSettled {
err := setSettleMetaFields(
settleIndex, invoiceNum, &invoice, now, nil,
)
if err != nil {
return nil, err
}
}
}
// The set of HTLC pre-images will only be set if we were actually able
// to reconstruct all the AMP pre-images.
var settleEligibleAMP bool
if update.State != nil {
settleEligibleAMP = len(update.State.HTLCPreimages) != 0
}
// With any invoice level state transitions recorded, we'll now
// finalize the process by updating the state transitions for
// individual HTLCs
var (
settledSetIDs = make(map[invpkg.SetID]struct{})
amtPaid lnwire.MilliSatoshi
)
for key, htlc := range invoice.Htlcs {
// Set the HTLC preimage for any AMP HTLCs.
if setID != nil && update.State != nil {
preimage, ok := update.State.HTLCPreimages[key]
switch {
// If we don't already have a preimage for this HTLC, we
// can set it now.
case ok && htlc.AMP.Preimage == nil:
htlc.AMP.Preimage = &preimage
// Otherwise, prevent over-writing an existing
// preimage. Ignore the case where the preimage is
// identical.
case ok && *htlc.AMP.Preimage != preimage:
return nil, invpkg.ErrHTLCPreimageAlreadyExists
}
}
// The invoice state may have changed and this could have
// implications for the states of the individual htlcs. Align
// the htlc state with the current invoice state.
//
// If we have all the pre-images for an AMP invoice, then we'll
// act as if we're able to settle the entire invoice. We need
// to do this since it's possible for us to settle AMP invoices
// while the contract state (on disk) is still in the accept
// state.
htlcContextState := invoice.State
if settleEligibleAMP {
htlcContextState = invpkg.ContractSettled
}
htlcSettled, err := updateHtlc(
now, htlc, htlcContextState, setID,
)
if err != nil {
return nil, err
}
// If the HTLC has being settled for the first time, and this
// is an AMP invoice, then we'll need to update some additional
// meta data state.
if htlcSettled && invoiceIsAMP {
settleHtlcsAmp(
&invoice, settledSetIDs, htlcsAmpUpdate, htlc,
key,
)
}
accepted := htlc.State == invpkg.HtlcStateAccepted
settled := htlc.State == invpkg.HtlcStateSettled
invoiceStateReady := accepted || settled
if !invoiceIsAMP {
// Update the running amount paid to this invoice. We
// don't include accepted htlcs when the invoice is
// still open.
if invoice.State != invpkg.ContractOpen &&
invoiceStateReady {
amtPaid += htlc.Amt
}
} else {
// For AMP invoices, since we won't always be reading
// out the total invoice set each time, we'll instead
// accumulate newly added invoices to the total amount
// paid.
if _, ok := update.AddHtlcs[key]; !ok {
continue
}
// Update the running amount paid to this invoice. AMP
// invoices never go to the settled state, so if it's
// open, then we tally the HTLC.
if invoice.State == invpkg.ContractOpen &&
invoiceStateReady {
amtPaid += htlc.Amt
}
}
}
// For non-AMP invoices we recalculate the amount paid from scratch
// each time, while for AMP invoices, we'll accumulate only based on
// newly added HTLCs.
if !invoiceIsAMP {
invoice.AmtPaid = amtPaid
} else {
invoice.AmtPaid += amtPaid
}
// As we don't update the settle index above for AMP invoices, we'll do
// it here for each sub-AMP invoice that was settled.
for settledSetID := range settledSetIDs {
settledSetID := settledSetID
err := setSettleMetaFields(
settleIndex, invoiceNum, &invoice, now, &settledSetID,
)
if err != nil {
return nil, err
}
}
// 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
}
// If this is an AMP invoice, then we'll actually store the rest of the
// HTLCs in-line with the invoice, using the invoice ID as a prefix,
// and the AMP key as a suffix: invoiceNum || setID.
if invoiceIsAMP {
err := updateAMPInvoices(invoices, invoiceNum, htlcsAmpUpdate)
if err != nil {
return nil, err
}
}
return &invoice, nil
}
// cancelHTLCs tries to cancel the htlcs in the given InvoiceUpdateDesc.