-
Notifications
You must be signed in to change notification settings - Fork 118
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
tapchannel: enforce strict forwarding for asset invoices #1144
Conversation
Pull Request Test Coverage Report for Build 11614783416Details
💛 - Coveralls |
Before assigning reviewers, tests will need to be added. |
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.
Nice approach! And great to have a unit test. Though I wonder what would actually happen on the sender and receiver side with this change? My assumption is that things would just time out (rather than rejecting the HTLC).
So I think we should also have an integration test for this.
tapchannel/aux_invoice_manager.go
Outdated
sellQuote, isSell := acceptedSellQuotes[rfqmsg.SerialisedScid(scid)] | ||
|
||
switch { | ||
case isBuy: |
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 wonder: Shouldn't an invoice always relate to a buy order only? Even in a direct peer payment, when I create an invoice, there should be a buy quote for it.
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.
Still unaddressed. If there's no good reason why we'd eve want to check a sell order, I think we should change this to only look at buy orders.
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.
Turns out I was wrong here! In case of a direct-peer payment through an asset invoice, it can actually be a sell order SCID. The itest failed here, so will update it.
6f724f2
to
950d0ae
Compare
An itest that covers this behavior has been added in a litd PR |
Will enhance the |
d3e0aef
to
87a1727
Compare
87a1727
to
a1e4157
Compare
A failing case (with the PR as-is, I think this seed is invalid if we change any of the generators):
Which fails here: Discovered after running the test for To run for more iterations: cd tapchannel
go test -run TestAuxInvoiceManagerProperty -rapid.checks=100_000 |
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.
Solid start with the property tests! Definitely headed in the right direction.
The actual implementation changes look reasonable, left some notes on test improvements.
1bbe907
to
d74dd65
Compare
dcf1c50
to
3a80ed5
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.
Looks very close! Will do final review once dependencies are in.
tapchannel/aux_invoice_manager.go
Outdated
sellQuote, isSell := acceptedSellQuotes[rfqmsg.SerialisedScid(scid)] | ||
|
||
switch { | ||
case isBuy: |
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.
Still unaddressed. If there's no good reason why we'd eve want to check a sell order, I think we should change this to only look at buy orders.
3a80ed5
to
54c11de
Compare
54c11de
to
9af79a6
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, just a couple of last nits (and one CI failure).
9af79a6
to
9a0c9c0
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.
Resetting my reviewer state.
9a0c9c0
to
9dedb3b
Compare
9dedb3b
to
d05ab4d
Compare
d05ab4d
to
1f955be
Compare
Okay, I rolled back the I should've just read the Godoc of the method, it was always right there 😅
|
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! Generators look a lot better.
I think we can still simplify them more with other rapid built-ins but this definitely works for now.
// TestAuxInvoiceManagerProperty runs property based tests on the | ||
// AuxInvoiceManager. | ||
func TestAuxInvoiceManagerProperty(t *testing.T) { | ||
t.Parallel() |
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 think rapid
tests are not thread safe? Not sure if that meant between multiple rapid
tests though, or just any other test.
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.
Yeah, that's possible. But the t.Parallel()
only means other tests in this file can run in parallel to the rapid test. And since we don't have any other rapid tests running there, this should be fine.
Tested for 2,000,000 iterations, looks good! |
Wanted to provide a bit of drive by review here, re the usage of property based tests. I think the best way to approach property bsaed tests is from a black-box angle. So you come up with some invariants a given function/method should hold, then generate random inputs, prune that space to be relevant, and assert the output based on input. A trivial example of this is encoding, we want Glancing at this PR, I think the property tests are too white box, and too coarse. They use state in between each test to execute assertions, and re-compute a lot of intermediate values to attempt to assert correct behavior. In short, they're written in "normal" white box manner. If we take a step back and think about what we wanted here, we want an invariant that goes something like:
This is the invariant that would prevent a known payment hash from being accepted with a normal HTLC, rather than an asset HTLC. If we look at the commit that added this logic, we see this section was changed: ad05718#diff-5761d8e06dd213a5ff31aca2abe70153485d5d7832da64b35d371c0303e42bbdR156-R167. Then we can go another step up to also test the htlc wire custom records recognition. To do this, we'd need to break up the If we wanted to test the bit that handles summing up the set of HTLCs, then rather than re-implement the logic to do a white box test, we can use another invariant. This might be somewhere along the lines of:
|
The package also has some support for testing more stateful machines which may be useful in the future, haven't tried it out myself though: https://pkg.go.dev/pgregory.net/rapid#T.Repeat |
This PR adds a few extra steps to the
AuxInvoiceManager
before it settles an invoice. Previously we wouldn't check that we received an asset HTLC for an asset invoice, leading to some undesired behavior.With these changes we enforce that if the invoice corresponds to an asset invoice then we only settle it if we received assets.
Todo:
Closes #1008