-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
channeldb: split UpdateInvoice
logic
#7377
channeldb: split UpdateInvoice
logic
#7377
Conversation
UpdateInvoice
logicUpdateInvoice
logic
d6fa424
to
89b3671
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the necessity to break this up and make the current invoice update handling more separated 💯. It feels quite difficult to get all things right at once here, especially with AMP in the mix. Could one extract AMP code paths perhaps in their own functions as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Easy to follow PR 🥇 Still trying to grok some of what is happening. Have a Q regarding using explicit types.
89b3671
to
22f45d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks close to me 🚀, nice commit restructures!
@bhandras: review reminder |
22f45d7
to
40ce742
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round looks good. Very nice commit structure, easy to follow👍 So happy we are refactoring this part of the code, which makes the following fix in #7463 easier🙏
Left some comments and questions. Will read more about AMP and then come for a second round!
|
||
// SettleHodlInvoiceUpdate indicates that this update settles one or | ||
// more HTLCs from a hodl invoice. | ||
SettleHodlInvoiceUpdate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't read the full PR, just one more state pops into my head. Maybe there needs to be a SettleHTLCsUpdate
? Since we have CancelHTLCsUpdate
vs CancelInvoiceUpdate
.
update *invpkg.InvoiceUpdateDesc) (*invpkg.Invoice, error) { | ||
|
||
var setID *[32]byte | ||
invoiceIsAMP := invoice.IsAMP() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just thinking out of the box...I wonder if it's easier to create two functions, one for adding htlcs for AMP addHTLCsAMP
, and the other for MPP, since they have a different logical flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incoming in the next PR, I did it this way so this PR did not need to include changes in the tests (easier to review + build knowledge about the related code)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it this way so this PR did not need to include changes in the tests
what did you mean by this way
? probably should review the next PR now...😂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not changing the interface
Make the kind of update explicit in the `InvoiceUpdateDesc` struct.
40ce742
to
3f4bb48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some questions/comments, once addressed this is good to go⛵️
|
||
invoiceIsAMP = invoice.IsAMP() | ||
if invoiceIsAMP { | ||
setID = update.SetID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So when we cancel an htlc for an amp invoice we set it in the top level
so this is to reflect the above comment right? basically the line setID = (*[32]byte)(update.SetID)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right
} | ||
|
||
if err := invoices.Put(invoiceNum, buf.Bytes()); err != nil { | ||
err := d.serializeAndStoreInvoice(invoices, invoiceNum, invoice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
non-blocking: are there any reasons that we call this serializeAndStoreInvoice
at multiple places? Instead of using it in cancelHTLCs
, addHTLCs
and settleHodlInvoice
separately, I think we could just call it outside the switch update.UpdateType {
, and return d.serializeAndStoreInvoice
, seems like a few more lines were saved and fewer params used.
Or, do you plan to further make these actions into independent db tx(which is nice IMO)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each one will be its own db interface method. I would make the change if this code was going to survive but it won't 🎯
) | ||
|
||
// 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 | ||
newState = update.State.NewState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this seems to be the wrong commit to remove it, was it because it was previously used in cancelSingleHtlc
and now the compiler is complaining if it's not removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mmm.. are we talking about the second commit? I am able to compile and run the tests (make unit
) without any problem 👀
update *invpkg.InvoiceUpdateDesc) (*invpkg.Invoice, error) { | ||
|
||
var setID *[32]byte | ||
invoiceIsAMP := invoice.IsAMP() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it this way so this PR did not need to include changes in the tests
what did you mean by this way
? probably should review the next PR now...😂
Previous to this commit we were able to call `UpdateInvoice` with an updated that added and cancelled htlcs at the same time. The function returned an error if there was overlapping between the two htlc set. However, that behavior was not used in the LND code itself. Eventually we want to split this method in multiple ones, among them one for canceling htlcs and another one for adding them. For that reason, this behavior is not supported anymore.
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.
3f4bb48
to
034853a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM🎉 Confirmed the itest failures are flake.
One more question: should this be based on |
The
InvoiceDB
interface has one method a method that takes care of updating an invoice. An invoice can be updated in multiple ways, it is up to the caller to decide how an invoice need to be updated and persisted using one of the function arguments.The method will load the current invoice state from the db and apply a callback provided by the user. The callback needs to return an
InvoiceUpdateDesc
. Depending on the kind of update, theInvoiceUpdateDesc
will be populated with information that will be used to update the db entry. BecauseUpdateInvoice
is used in multiple scenarios (cancel an htlc, settle an invoice, cancel an invoice etc...) theInvoiceUpdateDesc
bundles parameters used in each type of update. No update will ever use all the fields of the struct.Because the flow for every kind of update + invoice type (bolt11 vs AMP) is mixed it is hard to follow what constraints the
InvoiceUpdateDesc
fields have + what parts get modified in every type of call.The objective of this PR is to split the logic of each type of update that is allowed. This would allow keep better track of the each update flow, logically decouple the flows of each update type and possibly prepare the path to split this method in multiple ones.
Now that the InvoiceDB interface is exposed and other people can code and plug their own implementations it may make sense to have a clear API to what needs to be persisted in each method while keeping the checks of what is allowed in the
invoices
package.NOTE: things to take into account
InvoiceUpdateDesc
so the callback needs to take care of setting them.