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

feat(math): Upstream GDA based decimal type #20085

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open

feat(math): Upstream GDA based decimal type #20085

wants to merge 18 commits into from

Conversation

samricotta
Copy link
Collaborator

@samricotta samricotta commented Apr 18, 2024

Description

Closes: #11783

Upstreams the GDA decimal type within math and separated the dec with the legacy dec. In addition added benchmarks for the new type in comparison to legacy.

Please see the benchmarking results below:

BenchmarkCompareLegacyDecAndNewDec/LegacyDec-10    	 8621032	       143.8 ns/op	     144 B/op	       3 allocs/op
BenchmarkCompareLegacyDecAndNewDec/NewDec-10       	 5206173	       238.7 ns/op	     176 B/op	       7 allocs/op
BenchmarkCompareLegacyDecAndNewDecQuoInteger/LegacyDec-10         	 5767692	       205.1 ns/op	     232 B/op	       6 allocs/op
BenchmarkCompareLegacyDecAndNewDecQuoInteger/NewDec-10            	23172602	        51.75 ns/op	      16 B/op	       2 allocs/op
BenchmarkCompareLegacyAddAndDecAdd/LegacyDec-10                   	21157941	        56.33 ns/op	      80 B/op	       2 allocs/op
BenchmarkCompareLegacyAddAndDecAdd/NewDec-10                      	24133659	        48.92 ns/op	      48 B/op	       1 allocs/op
BenchmarkCompareLegacySubAndDecMul/LegacyDec-10                   	14256832	        87.47 ns/op	      80 B/op	       2 allocs/op
BenchmarkCompareLegacySubAndDecMul/NewDec-10                      	18273994	        65.68 ns/op	      48 B/op	       1 allocs/op
BenchmarkCompareLegacySubAndDecSub/LegacyDec-10                   	19988325	        64.46 ns/op	      80 B/op	       2 allocs/op
BenchmarkCompareLegacySubAndDecSub/NewDec-10                      	27430347	        42.45 ns/op	       8 B/op	       1 allocs/op

Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

  • New Features

    • Introduced a new decimal structure (Dec) for enhanced safety and precision in arithmetic operations across various modules.
    • Added benchmarking for new vs. legacy decimal operations.
    • New helper functions for mathematical calculations and parsing in the ecocredit module.
    • Updated documentation and module interfaces to use the new Dec structure.
  • Documentation

    • Updated architectural and module documentation to reflect changes in decimal handling and functionality.
  • Tests

    • Added new test cases and benchmarks to assess the performance and correctness of the new decimal operations.
    • Implemented a decimal migration testing function and removed outdated test comments.
  • Bug Fixes

    • Adjusted context setup in test functions to ensure proper execution environments.

@samricotta samricotta requested a review from a team as a code owner April 18, 2024 11:35
@samricotta samricotta marked this pull request as draft April 18, 2024 11:35
Copy link
Contributor

coderabbitai bot commented Apr 18, 2024

Important

Auto Review Skipped

Review was skipped due to path filters

Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The updates primarily focus on transitioning from the LegacyDec struct to the new Dec struct, a safer and more precise wrapper around apd.Decimal. This change involves updating various files to accommodate the new decimal handling, including updates in arithmetic operations, type signatures, and data types across different modules. Additionally, new benchmark tests and migration utilities are introduced to facilitate and evaluate the transition.

Changes

File Path Change Summary
math/dec.go, math/dec_legacy.go Replaced LegacyDec with Dec, updated methods and constants for precision and arithmetic operations.
math/dec_bench_test.go Introduced benchmarking functions for comparing legacy and new decimal operations.
math/math.go, types/dec_coin.go Added helper functions and new DecCoin creation function.
docs/.../adr-069-gov-improvements.md, x/distribution/README.md, x/mint/README.md, docs/build/.../18-decimal-handling.md Updated documentation and READMEs to reflect the use of math.Dec instead of math.LegacyDec.
testutil/... Added new tests and migration functions for decimals in testutil package.

Assessment against linked issues

Objective Addressed Explanation
Implement a GDA-based decimal type to replace sdk.Dec [#11783] The new Dec struct based on apd.Decimal addresses this requirement.
Implement lazy migration strategy from LegacyDec to Dec [#20249] The PR includes migration utilities but does not clearly specify if a lazy migration strategy using character prefixes is implemented.

Possibly related issues

  • Issue Math improvements #17750: This PR could potentially address the math improvements suggested, especially regarding non-mutating methods and JSON marshaling inconsistencies, aligning with the transition to a more robust decimal handling.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • 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/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@julienrbrt julienrbrt changed the title refactor(math): Upstream GDA based decimal type feat(math): Upstream GDA based decimal type Apr 18, 2024
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.

Actionable comments posted: 11

math/dec_legacy.go Show resolved Hide resolved
math/math.go Show resolved Hide resolved
math/math.go Show resolved Hide resolved
math/math.go Show resolved Hide resolved
math/dec.go Show resolved Hide resolved
math/dec.go Show resolved Hide resolved
math/dec.go Show resolved Hide resolved
math/dec.go Show resolved Hide resolved
math/dec.go Show resolved Hide resolved
@samricotta samricotta marked this pull request as ready for review April 18, 2024 13:13
Copy link
Member

@tac0turtle tac0turtle left a comment

Choose a reason for hiding this comment

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

can we adjust docs where legacy dec is used to use the new type in this pr?

// get the precision multiplier, do not mutate result
func precisionMultiplier(prec int64) *big.Int {
if prec < 0 {
panic(fmt.Sprintf("negative precision %v", prec))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
}

if prec > LegacyPrecision {
panic(fmt.Sprintf("too much precision, maximum %v, provided %v", LegacyPrecision, prec))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
func (d LegacyDec) RoundInt64() int64 {
chopped := chopPrecisionAndRoundNonMutative(d.i)
if !chopped.IsInt64() {
panic("Int64() out of bound")

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
@github-actions github-actions bot added C:x/distribution distribution module related C:x/mint Type: ADR labels Apr 22, 2024
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.

Actionable comments posted: 0

Actionable comments outside the diff hunks (1)
x/distribution/README.md (1)

Line range hint 84-86: Adjust the indentation of the unordered list to improve the markdown formatting.

- * [Concepts](#concepts)
- * [State](#state)
-     * [Validator Distribution](#validator-distribution)
+ * [Concepts](#concepts)
+ * [State](#state)
+   * [Validator Distribution](#validator-distribution)

Copy link
Member

@julienrbrt julienrbrt left a comment

Choose a reason for hiding this comment

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

We should revert all the docs modifications, as it isn't correct. It still uses LegacyDec.

@samricotta
Copy link
Collaborator Author

Not sure if all of the changes from LegacyDec to Dec should be in this PR though as it should probably be separated out into separate PR's

@julienrbrt
Copy link
Member

Not sure if all of the changes from LegacyDec to Dec should be in this PR though as it should probably be separated out into separate PR's

Yes, so we should revert the documentation changes then and only update them when we actually migrate a module imho

This reverts commit 115ecc4.
@github-actions github-actions bot removed C:x/distribution distribution module related C:x/mint Type: ADR labels Apr 22, 2024
@tac0turtle
Copy link
Member

tac0turtle commented Apr 23, 2024

sorry i didnt mean update the docs in the way that was done here. I meant add/modify docs that show users to use legacydec. can we add docs in how to build a module on what math type should be used. additional a note saying the sdk uses the legacy dec but this is the replacement. Then how could users migrate, or can they even. A module that uses legacy dec, how can it interpret a new dec value? The docs may not exist at all so we should add them

@samricotta
Copy link
Collaborator Author

Should these docs changes be in a separate PR ? Because from what I'm seeing, it will have to not only be added into the tutorial (which needs to be created) but I think should also have an additional section probably in building modules and throughout the docs as math isnt really referenced anywhere in the docs as it currently stands.

@tac0turtle
Copy link
Member

This pr is quite slim don't think it needs a separate pr.

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.

Actionable comments posted: 1

Out of diff range and nitpick comments (1)
docs/build/building-modules/18-decimal-handling.md (1)

12-12: Consider adding a comma after "decimals" for better readability.

Comment on lines 22 to 33
```
BenchmarkCompareLegacyDecAndNewDec/LegacyDec-10 8621032 143.8 ns/op 144 B/op 3 allocs/op
BenchmarkCompareLegacyDecAndNewDec/NewDec-10 5206173 238.7 ns/op 176 B/op 7 allocs/op
BenchmarkCompareLegacyDecAndNewDecQuoInteger/LegacyDec-10 5767692 205.1 ns/op 232 B/op 6 allocs/op
BenchmarkCompareLegacyDecAndNewDecQuoInteger/NewDec-10 23172602 51.75 ns/op 16 B/op 2 allocs/op
BenchmarkCompareLegacyAddAndDecAdd/LegacyDec-10 21157941 56.33 ns/op 80 B/op 2 allocs/op
BenchmarkCompareLegacyAddAndDecAdd/NewDec-10 24133659 48.92 ns/op 48 B/op 1 allocs/op
BenchmarkCompareLegacySubAndDecMul/LegacyDec-10 14256832 87.47 ns/op 80 B/op 2 allocs/op
BenchmarkCompareLegacySubAndDecMul/NewDec-10 18273994 65.68 ns/op 48 B/op 1 allocs/op
BenchmarkCompareLegacySubAndDecSub/LegacyDec-10 19988325 64.46 ns/op 80 B/op 2 allocs/op
BenchmarkCompareLegacySubAndDecSub/NewDec-10 27430347 42.45 ns/op 8 B/op 1 allocs/op
```
Copy link
Contributor

Choose a reason for hiding this comment

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

Replace hard tabs with spaces in the benchmarking code block for consistency with Markdown formatting standards.

Copy link
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

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

Very nice work! I have not completed the review yet but I want to share some thoughts already to discuss.


* **Enhanced Precision**: `Dec` uses the [apd](https://github.com/cockroachdb/apd) library for arbitrary precision decimals, suitable for accurate financial calculations.
* **Immutable Operations**: `Dec` operations are safer for concurrent use as they do not mutate the original values.
* **Better Performance**: `Dec` operations are faster and more efficient than `LegacyDec`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Very good to explain the motivation!

suite.Suite
}

func TestDecimalTestSuite(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

personal preference: there is no need for a test suite as there is no global state or a system under test setup. I find vanilla Go tests much more readable.

func NewNonNegativeDecFromString(s string) (Dec, error) {
d, err := NewDecFromString(s)
if err != nil {
return Dec{}, ErrInvalidDecString.Wrap(err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: here and others: the error returned from NewDecFromString is namespaced already. No need wrap them again. This would give an odd error string

new(big.Int).Mul(i.BigIntMut(), precisionMultiplier(prec)),
func NewDecFromString(s string) (Dec, error) {
if s == "" {
s = "0"
Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 I would expect an error for an empty string. Can you elaborate on the use cases?

Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed that apd also supports some strings like NaN, sNaN, Infinity, inf,...
You prevent infinite but would it make sense to limit this type to pure numeric strings as in LegacyDec? If people assume same behaviour, this may open up some fraud scenarios.

Copy link
Member

Choose a reason for hiding this comment

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

I think we should limit this to pure numeric strings and prohibit NaN, etc. I'm thinking that likely the handling of empty string as zero was considered convenience

// Format format decimal state
func (d LegacyDec) Format(s fmt.State, verb rune) {
_, err := s.Write([]byte(d.String()))
func NewPositiveDecFromString(s string) (Dec, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the difference between this and NewNonNegativeDecFromString ? If possible, let's get rid of one constructor. Personally, I prefer this method name over the double negative.

Copy link
Member

Choose a reason for hiding this comment

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

Positive can't be zero where as NonNegative can be zero. I think that's the difference, but we should optimize this API generally for what's going to be the best UX


bzInt, err := d.i.MarshalText()
func NewPositiveFixedDecFromString(s string, max uint32) (Dec, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I have noticed the variety of constructor methods that include different types and a checks. This does not scale well. If you can refactor the checks to some more generic approach, this may not go wild in the future:

type SetupConstraint func(Dec) error
func NotNegative() SetupConstraint {
	return func(d Dec) error {
		if d.IsNegative() {return ErrInvalidDecString.Wrap("is negative") }
		return nil
	}
}
func MaxDecimals(max uint32) SetupConstraint {
	return func(d Dec) error { 
		if d.NumDecimalPlaces() > max {return ErrInvalidDecString.Wrapf("exceeds maximum decimal places: %d", max) }
		return nil
	}
}
func NewDecFromString(s string, c ...SetupConstraint) (Dec, error) {
...
	// apply setup constraints
	for _, v := range c {
		if err := v(d1); err != nil {
			return Dec{}, err
		}
	}
	return d1, nil
}

Copy link
Member

Choose a reason for hiding this comment

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

We probably shouldn't consider the existing constructors to be the ideal API, let's review all this and upgrade.

return value
}
// NewDecFinite returns a decimal with a value of coeff * 10^exp.
func NewDecFinite(coeff int64, exp int32) Dec {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was confused by the name but I am not a native speaker. Is this the same functionality as LegacyNewDecWithPrec was? Then this name could be used to make it easier to find or

Suggested change
func NewDecFinite(coeff int64, exp int32) Dec {
func NewDecimalFromCoefficientExponent(coeff int64, exp int32) Dec {

)

type decimalTestSuite struct {
suite.Suite
func TestDec(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I have not used rapid before but I would feel more comfortable to see some sanity checks on the methods to ensure basic assumptions are correct. This will help with regression as well.

Copy link
Member

@aaronc aaronc Apr 30, 2024

Choose a reason for hiding this comment

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

Having both property based testing (i.e. rapid) plus table tests with specific cases would be ideal. Property based testing can look for edge cases and rapid also works with go fuzz. Table tests will make sure we cover a well defined set of known cases. Doing both is ideal IMHO

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.

Actionable comments posted: 2

Out of diff range and nitpick comments (2)
testutil/dec.go (1)

12-37: Consider adding documentation for the DiffDecimalsMigration function.

It would be beneficial to include a comment describing the purpose and usage of this function, especially since it involves data migration and integrity checks which are critical operations.

testutil/math_utils_test.go (1)

43-45: Clarify the use of 0xFF in prefixRange.

Adding a comment to explain why 0xFF is appended to the prefix in prefixRange would improve code readability and maintainability, especially for new developers or external contributors.

Comment on lines 16 to 29
func TestDiffDecimalsMigration(t *testing.T) {
key := storetypes.NewKVStoreKey("test")
ctx := testutil.DefaultContext(key, storetypes.NewTransientStoreKey("transient"))
for i := int64(0); i < 5; i++ {
legacyDec := math.LegacyNewDec(i)
dec := math.NewDecFromInt64(i)
ctx.KVStore(key).Set([]byte(fmt.Sprintf("legacy_%d", i)), []byte(legacyDec.String()))
ctx.KVStore(key).Set([]byte(fmt.Sprintf("new_%d", i)), []byte(dec.String()))
}

hashLegacy := computeHash(ctx, key, "legacy_")
hashNew := computeHash(ctx, key, "new_")
require.Equal(t, hashLegacy, hashNew, "Hashes do not match")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Enhance the test coverage for DiffDecimalsMigration.

The current test only checks for hash equality but does not verify the correctness of the migration logic itself. Would you like me to help by adding more comprehensive tests or opening a GitHub issue to track this enhancement?

Comment on lines 31 to 41
func computeHash(ctx sdk.Context, key storetypes.StoreKey, prefix string) string {
h := sha256.New()
start, end := prefixRange(prefix)
it := ctx.KVStore(key).Iterator(start, end)
defer it.Close()
for ; it.Valid(); it.Next() {
h.Write(it.Key())
h.Write(it.Value())
}
return hex.EncodeToString(h.Sum(nil))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize the computeHash function.

Consider using a more efficient way to handle byte slices in computeHash. Currently, the function recalculates the hash for each prefix, which might be optimized.

This reverts commit 9f3fc57.
new(big.Int).Mul(i.BigIntMut(), precisionMultiplier(prec)),
func NewDecFromString(s string) (Dec, error) {
if s == "" {
s = "0"
Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed that apd also supports some strings like NaN, sNaN, Infinity, inf,...
You prevent infinite but would it make sense to limit this type to pure numeric strings as in LegacyDec? If people assume same behaviour, this may open up some fraud scenarios.

return chopPrecisionAndRound(tmp)
// Quo returns a new Dec with value `x/y` (formatted as decimal128, 34 digit precision) without mutating any
// argument and error if there is an overflow.
func (x Dec) Quo(y Dec) (Dec, error) {
Copy link
Contributor

@alpe alpe Apr 25, 2024

Choose a reason for hiding this comment

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

I did some tests with Quo and the precision is much higher than 34 digits. Do you need to do rounding here? Working with NaN caused some for me unexpected behaviour. Examples:
https://gist.github.com/alpe/5a27babec8005fa347fdd0f0094b1a75

Copy link
Member

Choose a reason for hiding this comment

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

Maybe, we should make sure we agree on the expected behavior and then have tests to check it.

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.

Actionable comments posted: 1

Comment on lines +44 to +45
if amount.IsNegative() {
panic(fmt.Sprintf("negative decimal coin amount: %v\n", amount))
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider improving the panic message for clarity.

- panic(fmt.Sprintf("negative decimal coin amount: %v\n", amount))
+ panic(fmt.Sprintf("attempted to create DecCoin with negative amount: %v", amount))

This change makes the error message more specific about the error condition and removes the unnecessary newline character.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
if amount.IsNegative() {
panic(fmt.Sprintf("negative decimal coin amount: %v\n", amount))
if amount.IsNegative() {
panic(fmt.Sprintf("attempted to create DecCoin with negative amount: %v", amount))

@aaronc
Copy link
Member

aaronc commented Apr 30, 2024

Would be good to have some reference to the original provenance of this code coming from https://github.com/regen-network/regen-ledger/tree/main/types/math

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.

Actionable comments posted: 5

Out of diff range and nitpick comments (5)
docs/build/building-modules/18-decimal-handling.md (5)

8-8: Consider adding a comma before "but" to improve readability.


14-14: Add a comma after "use" for grammatical correctness.


20-20: Add a comma after "example" to improve the flow of the sentence.


111-111: Add a comma after "migration" to improve readability.


Line range hint 125-125: Remove the extra blank line to maintain consistency in document formatting.

- 

docs/build/building-modules/18-decimal-handling.md Outdated Show resolved Hide resolved
* **Immutable Operations**: `Dec` operations are safer for concurrent use as they do not mutate the original values.
* **Better Performance**: `Dec` operations are faster and more efficient than `LegacyDec`.`

## Using `Dec` in Modules that havent used `LegacyDec`
Copy link
Contributor

Choose a reason for hiding this comment

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

Correct the spelling of "haven't" in the heading.

- ## Using `Dec` in Modules that havent used `LegacyDec`
+ ## Using `Dec` in Modules that haven't used `LegacyDec`

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
## Using `Dec` in Modules that havent used `LegacyDec`
## Using `Dec` in Modules that haven't used `LegacyDec`

docs/build/building-modules/18-decimal-handling.md Outdated Show resolved Hide resolved
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.

Actionable comments posted: 37

math/dec_legacy.go Show resolved Hide resolved
math/dec_legacy.go Show resolved Hide resolved
math/dec_legacy.go Show resolved Hide resolved
math/dec_legacy.go Show resolved Hide resolved
math/dec_legacy.go Show resolved Hide resolved
math/dec_legacy_test.go Show resolved Hide resolved
math/dec_legacy_test.go Show resolved Hide resolved
math/dec_legacy_test.go Show resolved Hide resolved
math/dec_legacy_test.go Show resolved Hide resolved
math/dec_legacy_test.go Show resolved Hide resolved
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.

Actionable comments posted: 3

docs/build/building-modules/18-decimal-handling.md Outdated Show resolved Hide resolved

If you are creating a new module or updating an existing module that has not used `LegacyDec`, you can directly use `Dec` without any changes.

As an example we will use `DecCoin` which is a common type used in the Cosmos SDK.
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding a comma after "As an example" for better readability.

- As an example we will use `DecCoin` which is a common type used in the Cosmos SDK.
+ As an example, we will use `DecCoin` which is a common type used in the Cosmos SDK.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
As an example we will use `DecCoin` which is a common type used in the Cosmos SDK.
As an example, we will use `DecCoin` which is a common type used in the Cosmos SDK.

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.

Actionable comments posted: 1


```go
import (
"cosmossdk.io/math"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use spaces instead of tabs for indentation to maintain consistency in Markdown formatting.

-	"cosmossdk.io/math"
+    "cosmossdk.io/math"

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
"cosmossdk.io/math"
"cosmossdk.io/math"

@julienrbrt
Copy link
Member

Would be good to have some reference to the original provenance of this code coming from https://github.com/regen-network/regen-ledger/tree/main/types/math

+1, we should imho add a doc.go mentioning and maybe add co-authors to the commit?

Co-Authored-By: Aaron Craelius <aaronc@users.noreply.github.com>
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.

Actionable comments posted: 0

Review Details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits Files that changed from the base of the PR and between 0701e66 and e5e0f65.
Files selected for processing (1)
  • math/doc.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • math/doc.go

Comment on lines +32 to +42
b.Run("LegacyDec", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = legacyB1.Quo(LegacyNewDec(1))
}
})

b.Run("NewDec", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = newB1.QuoInteger(NewDecFromInt64(1))
}
})
Copy link
Contributor

Choose a reason for hiding this comment

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

These benchmarks are wrong, they benchmark the dec allocation along with Quo by one!

So we should allocate the one dec outside the loop!

But to do a useful benchmark, we need numbers at far bigger word sizes, not single word!

@@ -78,7 +78,8 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
Copy link

Choose a reason for hiding this comment

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

Curious why we landed on apd v2 instead of v3? Didn't see a discussion in either of #7773 (comment) or #11783 , just a brief mention. In some testing we did it showed 20-30% better performance improvements in overall runtime.

Copy link
Member

@aaronc aaronc May 13, 2024

Choose a reason for hiding this comment

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

This just looks like an oversight. The reference code was written a while ago (before v3) and this code should be updated to use the latest version

Copy link

Choose a reason for hiding this comment

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

Cool, thanks for the insight.

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.

upstream GDA based decimal type
7 participants