channeldb: split cancel and add htlc updates

Previously the cancel and add actions were combined in a single map.
Nil values implictly signaled cancel actions. This wasn't very obvious.
Furthermore this split prepares for processing the adds and cancels
separately, which is more efficient if there are already two maps.
This commit is contained in:
Joost Jager 2019-11-27 14:19:15 +01:00
parent c45891ecf7
commit a4a3c41924
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
4 changed files with 31 additions and 28 deletions

@ -686,7 +686,7 @@ func getUpdateInvoice(amt lnwire.MilliSatoshi) InvoiceUpdateCallback {
update := &InvoiceUpdateDesc{
Preimage: invoice.Terms.PaymentPreimage,
State: ContractSettled,
Htlcs: map[CircuitKey]*HtlcAcceptDesc{
AddHtlcs: map[CircuitKey]*HtlcAcceptDesc{
{}: {
Amt: amt,
},

@ -316,10 +316,12 @@ type InvoiceUpdateDesc struct {
// State is the new state that this invoice should progress to.
State ContractState
// Htlcs describes the changes that need to be made to the invoice htlcs
// in the database. Htlc map entries with their value set should be
// added. If the map value is nil, the htlc should be canceled.
Htlcs map[CircuitKey]*HtlcAcceptDesc
// CancelHtlcs describes the htlcs that need to be canceled.
CancelHtlcs map[CircuitKey]struct{}
// AddHtlcs describes the newly accepted htlcs that need to be added to
// the invoice.
AddHtlcs map[CircuitKey]*HtlcAcceptDesc
// Preimage must be set to the preimage when state is settled.
Preimage lntypes.Preimage
@ -1251,26 +1253,25 @@ func (d *DB) updateInvoice(hash lntypes.Hash, invoices, settleIndex *bbolt.Bucke
now := d.Now()
// Update htlc set.
for key, htlcUpdate := range update.Htlcs {
// Process cancel actions from update descriptor.
for key := range update.CancelHtlcs {
htlc, ok := invoice.Htlcs[key]
// No update means the htlc needs to be canceled.
if htlcUpdate == nil {
if !ok {
return nil, fmt.Errorf("unknown htlc %v", key)
}
if htlc.State != HtlcStateAccepted {
return nil, fmt.Errorf("can only cancel " +
"accepted htlcs")
}
htlc.State = HtlcStateCanceled
htlc.ResolveTime = now
invoice.AmtPaid -= htlc.Amt
continue
if !ok {
return nil, fmt.Errorf("unknown htlc %v", key)
}
if htlc.State != HtlcStateAccepted {
return nil, fmt.Errorf("can only cancel " +
"accepted htlcs")
}
htlc.State = HtlcStateCanceled
htlc.ResolveTime = now
invoice.AmtPaid -= htlc.Amt
}
// Process add actions from update descriptor.
for key, htlcUpdate := range update.AddHtlcs {
htlc, ok := invoice.Htlcs[key]
// Add new htlc paying to the invoice.
if ok {

@ -598,7 +598,7 @@ func (i *InvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {
// Mark individual held htlcs as canceled.
canceledHtlcs := make(
map[channeldb.CircuitKey]*channeldb.HtlcAcceptDesc,
map[channeldb.CircuitKey]struct{},
)
for key, htlc := range invoice.Htlcs {
switch htlc.State {
@ -615,13 +615,13 @@ func (i *InvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {
continue
}
canceledHtlcs[key] = nil
canceledHtlcs[key] = struct{}{}
}
// Move invoice to the canceled state.
return &channeldb.InvoiceUpdateDesc{
Htlcs: canceledHtlcs,
State: channeldb.ContractCanceled,
CancelHtlcs: canceledHtlcs,
State: channeldb.ContractCanceled,
}, nil
}

@ -130,7 +130,9 @@ func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) (
},
}
update := channeldb.InvoiceUpdateDesc{Htlcs: newHtlcs}
update := channeldb.InvoiceUpdateDesc{
AddHtlcs: newHtlcs,
}
// Don't update invoice state if we are accepting a duplicate payment.
// We do accept or settle the HTLC.