-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Fix ApproxRoot Infinite Looping #7140
Fix ApproxRoot Infinite Looping #7140
Conversation
Codecov Report
@@ Coverage Diff @@
## master #7140 +/- ##
=======================================
Coverage 54.78% 54.78%
=======================================
Files 563 563
Lines 38624 38624
=======================================
Hits 21162 21162
Misses 15730 15730
Partials 1732 1732 |
If this is accepted as-is, for Launchpad I'll propose a specific non-breaking patch + documentation and appropriate section in the release notes. @clevinson @ethanfrey |
types/decimal.go
Outdated
func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) { | ||
// The maximum number of iterations is required as a backup boundary condition for | ||
// cases where the answer never converges enough to satisfy the main condition. | ||
func (d Dec) ApproxRoot(root, maxIters uint64) (guess Dec, err error) { |
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 personally don't feel comfortable with this code. If this is necessary by the application, why not just define it there? We don't even use this in the SDK or relevant applications (e.g. gaia and simapp).
I would prefer to remove it outright.
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 understand. My reasoning is that it's nice to have root calculation functionality built into the SDK alongside the Dec type, but as you said one could implement it on the app side of things if they need it.
I'm curious if it's the solution approach that you don't feel comfortable with or the function/s in general? I could try a different approach if the former is the case.
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.
If we want to remove it outright, I can get that done instead of the above solution.
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 having a root function is pretty important for a Decimal/Number library, as its a pretty common operation. And implementing a solid version in the library itself would be better than having different applications all having their own potentially broken implementation (oops 😅).
When this is resolved, one way or the other, I agree with merging it into launchpad (after another review pass). |
This seems like a good solution to me. Do we want the end users to provide a MaxIterations, or just hardcode a reasonable default? Requiring them to provide it would need the user to understand the inner workings of how the function calculates roots, which seems unnecessary. |
I had these thoughts as well actually but my reasoning is that with any other function the user will always need to understand the inner workings to some extent. That being said, from my experimentation (and test cases included in the PR) it seems typically the number of iterations required is in the 10's (< 100), so maybe a default that could be used would be around 100. Not sure if there's a way in Go to allow the default to be bypassed for extra iterations without having to implement an extra function or complicating things elsehow. |
For what concerns Launchpad, I'd love to avoid breaking API and ABI, thus the folllowing:
might actually be a reasonable fix IMHO. Wdyt? @ethanfrey @clevinson |
Sounds good. Same API, just hardcoded max of 100. Avoids an attack vector and I doubt any real case will be too far off reality after 100 steps |
… inline doc and CHANGELOG accordingly.
I've updated the code and doc to instead use a hard-coded maximum number of iterations. Please check it out :) |
Co-authored-by: Alessio Treglia <[email protected]>
Co-authored-by: Alessio Treglia <[email protected]>
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 good to go! Thanks @migueldingli1997!
No problem. I just fixed 10 to 100 |
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 👍
@alexanderbez is in favor of removing the Whilst I acknowledge and partly agree with @alexanderbez's point, I suppose that @aaronc @clevinson I'd like to hear from you guys what you think! [1] Bez any mischaracterization is purely incidental, so please elaborate further if you believe I misunderstood your message :-) |
Looks good to me, I'm in agreement that an Given that we have |
@clevinson dixit:
I hear you brother, I hear you... (cit.) But that's a way longer conversation... |
This sounds fine for now. We should consider something like https://github.com/cockroachdb/apd long term |
@alexanderbez Considering #7140 (comment) and #7140 (comment), could we merge this in now then? Is there any other concerns do you reckon we should address before merging this in? |
No need to rest on my approval here. I still think we don't need half-baked APIs like this, but if there is a strong need for it, merge away 👍 |
Added a maximum number of iterations (100) to ApproxRoot (and ApproxSqrt) to serve as a hard limit on the number of iterations that the algorithm performs. If the answer converges before the maximum iterations, it returns immediately. Otherwise, if the answer never converges enough to satisfy the primary loop condition, the looping stops after a hundred iterations. Closes: #7038
Added a maximum number of iterations (100) to ApproxRoot (and ApproxSqrt) to serve as a hard limit on the number of iterations that the algorithm performs. If the answer converges before the maximum iterations, it returns immediately. Otherwise, if the answer never converges enough to satisfy the primary loop condition, the looping stops after a hundred iterations. Closes: #7038 Co-authored-by: Miguel Dingli <[email protected]>
Description
Closes: #7038
Added a maximum number of iterations (100) to
ApproxRoot
(andApproxSqrt
) to serve as a hard limit on the number of iterations that the algorithm performs. If the answer converges before the maximum iterations, it returns immediately. Otherwise, if the answer never converges enough to satisfy the primary loop condition, the looping stops after a hundred iterations.A test case showing a scenario where the answer never converges enough was added, with inline commenting.
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerCodecov Report
in the comment section below once CI passes