From 65fc8d72c652a8ea4208d90c32e634fb5cc86f34 Mon Sep 17 00:00:00 2001 From: positiveblue Date: Thu, 23 Feb 2023 06:53:24 -0800 Subject: [PATCH] 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. --- channeldb/invoices.go | 247 +----------------------------------------- 1 file changed, 4 insertions(+), 243 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index b8780600a..8f973fcba 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -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.