Skip to content
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

test(math): add fuzzer for LegacyDec.ApproxRoot to catch stark deviations #17770

Closed
wants to merge 2 commits into from

Conversation

odeke-em
Copy link
Collaborator

@odeke-em odeke-em commented Sep 15, 2023

This fuzzer performs a roundtrip comparison for square roots comparing the value from:

  • squaring LegacyDec.ApproxRoot(2) against itself then checking if the value is very close to the original whole value
  • comparing against the Go standard library's math/big.Float.Sqrt and panicking if we find a deviation of greater than 5%

It's great to note that the results from this library so far from fuzzing show a higher precision/accuracy than math/big.Float.Sqrt for example with:

LegacyDec.ApproxRoot(100000000000000000.000000000000000000, 2)
Stdlib sqrt:                                316227766.000000000000000000
cosmossdk.io/math.*Dec.ApproxSqrt:          316227766.016837933199889354
Python3.7.6: math.sqrt(100000000000000000): 316227766.01683795
LegacyDec.ApproxRoot(10000700000000000.000000000000000000, 2)
Stdlib sqrt:                               100003499.900000000000000000
cosmossdk.io/math.*Dec.ApproxSqrt:         100003499.938752143656215533
Python3.7.6: math.sqrt(10000700000000000): 100003499.93875214

Updates PR #16141
Updates PR #17725

Summary by CodeRabbit

Tests:

  • Introduced a new function FuzzLegacyDecApproxRoot in the math package for fuzz testing. This function tests the square root approximation with various input values, enhancing the robustness of the math package.
  • Added error handling and precision comparison calculations to improve the accuracy and reliability of the tests.

@odeke-em odeke-em force-pushed the math-add-fuzzer-for-ApproxRoot branch from 93a8619 to e13ea18 Compare September 19, 2023 19:54
@odeke-em odeke-em marked this pull request as ready for review September 19, 2023 19:54
@odeke-em odeke-em requested a review from a team as a code owner September 19, 2023 19:54
@github-prbot github-prbot requested review from a team, kocubinski and atheeshp and removed request for a team September 19, 2023 19:54
@julienrbrt julienrbrt changed the title test: math: add fuzzer for LegacyDec.ApproxRoot to catch stark deviations test(math): add fuzzer for LegacyDec.ApproxRoot to catch stark deviations Sep 23, 2023
…ions

This fuzzer performs a roundtrip comparison for square roots
comparing the value from:
* squaring LegacyDec.ApproxRoot(2) against itself then checking
if the value is very close to the original whole value
* comparing against the Go standard library's math/big.Float.Sqrt
and panicking if we find a deviation of greater than 5%

It's great to note that the results from this library so far from
fuzzing show a higher precision/accuracy than math/big.Float.Sqrt
for example with:

LegacyDec.ApproxRoot(100000000000000000.000000000000000000, 2)
Stdlib sqrt:                                316227766.000000000000000000
cosmossdk.io/math.*Dec.ApproxSqrt:          316227766.016837933199889354
Python3.7.6: math.sqrt(100000000000000000): 316227766.01683795

LegacyDec.ApproxRoot(10000700000000000.000000000000000000, 2)
Stdlib sqrt:                               100003499.900000000000000000
cosmossdk.io/math.*Dec.ApproxSqrt:         100003499.938752143656215533
Python3.7.6: math.sqrt(10000700000000000): 100003499.93875214

Updates PR #16141
Updates PR #17725
@odeke-em odeke-em force-pushed the math-add-fuzzer-for-ApproxRoot branch from e13ea18 to 4a57301 Compare October 1, 2023 06:11
// Firstly ensure that gotApproxSqrt * gotApproxSqrt is
// super duper close to the value of dec.
squared := gotApproxSqrt.Mul(gotApproxSqrt)
if !squared.Equal(dec) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This if condition is just an optimization, right? If so, I'd drop it for clarity.

Comment on lines +48 to +53
f.Fuzz(func(t *testing.T, input string) {
splits := strings.Split(input, ",")
if len(splits) < 2 {
// Invalid input, just skip over it.
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many input strings are going to be immediate rejected. I suggest tightening the fuzzing function to something like

func(t *testing.T, dec string, nthRoot uint64)

Further, I think you can avoid invalid strings by going through big.Rat:

func(t *testing.T, nomBytes, denomBytes []byte, nthRoot uint64)
   nom := big.Int{}.SetBytes(nomBytes)
   denom := big.Int{}.SetBytes(denomBytes)
  decRat := big.Rat{}.SetFrac(nom, denom)
  dec := big.Float{}.SetRat(decRat)

If you want negative numbers, add a bool argument to the fuzzing function.

Copy link
Contributor

coderabbitai bot commented Oct 31, 2023

Walkthrough

The introduced changes enhance the math package by adding a new fuzz testing function FuzzLegacyDecApproxRoot. This function tests the square root approximation with fuzzed inputs, ensuring precision and error handling. The changes also include new imports and variables to support these operations.

Changes

File Path Summary
math/fuzz_test.go The file now includes imports for math/big and strconv. A new function FuzzLegacyDecApproxRoot has been added for fuzz testing. New variables max5Percent and decDiv100 have been introduced. The function fuzzes input values for square root approximation, performs checks on the results, handles errors, and performs precision comparison calculations.

Poem

🐇 Hopping through the code, under the autumn moon's glow, 🍂

Changes we've sown, watch as they grow. 🌱

Fuzzing the roots, in the math we trust, 🧮

Precision and checks, in code we thrust. 💻

Celebrate the changes, for they're no small feat, 🎉

In the world of code, where logic and creativity meet. 🌍🤝

So here's to the coders, in every nation, 🌐

Your work is a source of endless fascination! 🎆

Validation with GitHub issue(Beta)

Assessment of the PR changes against GitHub Issue

Aspect Aligns with the linked issue Explanation
Code changes ✔️ The pull request introduces a new function FuzzLegacyDecApproxRoot for fuzz testing which aligns with the requirement of adding tests.
Performance improvement The pull request does not provide any explicit changes that would improve the performance of the Dec.Sqrt() routine, reduce heap allocations, or optimize constant re-use and mutative methods.
Documentation The pull request does not mention any updates to the documentation, which is a requirement in the GitHub issue.
Error handling ✔️ The pull request includes additions to handle errors which is a good practice in code changes, although it's not explicitly mentioned in the issue.
CI checks The pull request does not mention whether all CI checks have passed, which is a requirement in the GitHub issue.
 </details><!-- This is an auto-generated comment: raw summary by coderabbit.ai -->

Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f03b396 and 0553e60.
Files selected for processing (1)
  • math/fuzz_test.go (2 hunks)
Additional comments: 7
math/fuzz_test.go (7)
  • 1-8: The new imports are used appropriately in the fuzzing function. Ensure that these packages are included in your project dependencies.

  • 29-32: The global variables max5Percent and decDiv100 are used for precision comparison in the fuzzing function. Ensure that these values are appropriate for your use case.

  • 34-138: The FuzzLegacyDecApproxRoot function is well-structured and handles errors appropriately. It also includes checks to ensure the input is valid and the results are within the expected range. However, consider adding more comments to explain the logic and calculations, especially for the precision comparison and the use of max5Percent and decDiv100.

+ // max5Percent is the maximum allowed deviation (5%) between the square of the approximated root and the original value.
+ // decDiv100 is used to convert the deviation to a percentage.
  • 50-64: The function handles invalid inputs by simply returning without throwing an error. This is a good practice for fuzzing as it allows the function to continue testing with other inputs.

  • 78-84: The function handles errors from dec.ApproxRoot(nthRoot) appropriately. It skips over out-of-bounds errors and fails the test for other errors.

  • 92-100: The function checks if the square of the approximated root is close to the original value. If the difference exceeds 5%, it fails the test. This is a good practice for fuzzing as it helps identify significant deviations.

  • 102-136: The function compares the result of LegacyDec.ApproxRoot with the Go standard library's math/big.Float.Sqrt function. If the difference exceeds 5%, it fails the test. This is a good practice for fuzzing as it helps identify significant deviations.

@@ -22,3 +25,114 @@ func FuzzLegacyNewDecFromStr(f *testing.F) {
}
})
}

var (
max5Percent, _ = LegacyNewDecFromStr("5") // 5% max tolerance of difference in values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
max5Percent, _ = LegacyNewDecFromStr("5") // 5% max tolerance of difference in values
maxTolerance, _ = LegacyNewDecFromStr("5") // 5% max tolerance of difference in values

@tac0turtle
Copy link
Member

closing due to staleness

@tac0turtle tac0turtle closed this Nov 12, 2023
@tac0turtle tac0turtle deleted the math-add-fuzzer-for-ApproxRoot branch April 17, 2024 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants