channeldb: only accept/settle non-empty HTLC sets
Prior to AMP, there could only be one HTLC set. Now that there can be multiple, we introduce the inherent risk that we might be persisting a settle/accept of the wrong HTLC set. To migitigate this risk, we add a check to assert that an invoice can only be transitioned into an Accepted or Settled state if the specified HTLC set is non-empty, i.e. has accepted HTLCs. To do this check, we unroll the loops in UpdateInvoice to first process any added or canceled HTLCs. This ensures that the set of accepted HTLCs is up-to-date when we got to transition the invoice into a new state, at which point we can accurately check that the HTLC set is non-empty. Previously this sort of check wasn't possible because a newly added HTLC wouldn't be populated on the invoice when going to call updateInvoiceState. Once the invoice-level transition checks have completed, we complete a final pass to move the HTLCs into their final states and recompute the amount paid. With this refactor, it is now possible to make stronger assertions about the invoice and the state transitions being made by the invoiceregistry before those changes are ultimately persisted.
This commit is contained in:
2 files changed
+57
-32
No files matched your search
@@ -1421,6 +1421,13 @@ func TestSetIDIndex(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, invoice, &dbInvoiceBySetID)
|
||||
|
||||
// Now settle the first htlc set, asserting that the two htlcs with set
|
||||
// id 2 get canceled as a result.
|
||||
_, err = db.UpdateInvoice(
|
||||
ref, getUpdateInvoiceAMPSettle(&[32]byte{}),
|
||||
)
|
||||
require.Equal(t, ErrEmptyHTLCSet, err)
|
||||
|
||||
// Now settle the first htlc set, asserting that the two htlcs with set
|
||||
// id 2 get canceled as a result.
|
||||
dbInvoice, err = db.UpdateInvoice(ref, getUpdateInvoiceAMPSettle(setID))
|
||||
|
||||
Reference in new issue
Block a user