-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add decimal support to group module (#10035)
<!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description Closes: #9895 Add decimal support to group module based on a streamlined version of https://github.com/regen-network/regen-ledger/tree/3265a868bf834fb946da1facb81122e13e348538/types/math --- ### 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... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [x] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] 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](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
- Loading branch information
1 parent
58673f8
commit 6e70d25
Showing
5 changed files
with
391 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Package math provides helper functions for doing mathematical calculations and parsing for the ecocredit module. | ||
package math | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cockroachdb/apd/v2" | ||
|
||
"github.com/cosmos/cosmos-sdk/types/errors" | ||
) | ||
|
||
// Dec is a wrapper struct around apd.Decimal that does no mutation of apd.Decimal's when performing | ||
// arithmetic, instead creating a new apd.Decimal for every operation ensuring usage is safe. | ||
// | ||
// Using apd.Decimal directly can be unsafe because apd operations mutate the underlying Decimal, | ||
// but when copying the big.Int structure can be shared between Decimal instances causing corruption. | ||
// This was originally discovered in regen0-network/mainnet#15. | ||
type Dec struct { | ||
dec apd.Decimal | ||
} | ||
|
||
func NewDecFromString(s string) (Dec, error) { | ||
d, _, err := apd.NewFromString(s) | ||
if err != nil { | ||
return Dec{}, errors.ErrInvalidDecString.Wrap(err.Error()) | ||
} | ||
return Dec{*d}, nil | ||
} | ||
|
||
func NewDecFromInt64(x int64) Dec { | ||
var res Dec | ||
res.dec.SetInt64(x) | ||
return res | ||
} | ||
|
||
// Add returns a new Dec with value `x+y` without mutating any argument and error if | ||
// there is an overflow. | ||
func (x Dec) Add(y Dec) (Dec, error) { | ||
var z Dec | ||
_, err := apd.BaseContext.Add(&z.dec, &x.dec, &y.dec) | ||
return z, errors.Wrap(err, "decimal addition error") | ||
} | ||
|
||
// Sub returns a new Dec with value `x-y` without mutating any argument and error if | ||
// there is an overflow. | ||
func (x Dec) Sub(y Dec) (Dec, error) { | ||
var z Dec | ||
_, err := apd.BaseContext.Sub(&z.dec, &x.dec, &y.dec) | ||
return z, errors.Wrap(err, "decimal subtraction error") | ||
} | ||
|
||
func (x Dec) Int64() (int64, error) { | ||
return x.dec.Int64() | ||
} | ||
|
||
func (x Dec) Cmp(y Dec) int { | ||
return x.dec.Cmp(&y.dec) | ||
} | ||
|
||
func (x Dec) IsEqual(y Dec) bool { | ||
return x.dec.Cmp(&y.dec) == 0 | ||
} | ||
|
||
func (x Dec) IsNegative() bool { | ||
return x.dec.Negative && !x.dec.IsZero() | ||
} | ||
|
||
// Add adds x and y | ||
func Add(x Dec, y Dec) (Dec, error) { | ||
return x.Add(y) | ||
} | ||
|
||
// SubNonNegative subtracts the value of y from x and returns the result with | ||
// arbitrary precision. Returns an error if the result is negative. | ||
func SubNonNegative(x Dec, y Dec) (Dec, error) { | ||
z, err := x.Sub(y) | ||
if err != nil { | ||
return Dec{}, err | ||
} | ||
|
||
if z.IsNegative() { | ||
return z, fmt.Errorf("result negative during non-negative subtraction") | ||
} | ||
|
||
return z, nil | ||
} |
Oops, something went wrong.