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
Proto representation of types.Dec unintuitive and inconsistent #10863
Comments
Oh no 😱. So I think this should basically classified as a bug. It appears that the proto JSON is to actually use a decimal place (i.e. So I'm not really sure what to do. Fixing this on master would be state breaking and require migrations, and also break clients. At the same time, the current encoding is just simply wrong... We are planning to switch decimal implementations over to something that is GDA compliant, so an alternative would be to consider this
The struct approach may be a good way to go, but I'm not really sure it's preferable over a string. An alternative could be an int64 mantissa with an int32 exponent which should provide plenty of precision for most use cases. |
Thank you for your understanding and support on that issue, Aaron!
Same here
Sounds plausible
The string is more beginner friendly for sure. Also in many cases devs don't bother about the difference between decimals and floats. And it is probably okay for a lot of use cases such as displaying a rounded inflation rate. I was kindof leaning towards the struct to create a hard type break that hurts at compile time rather than silently changing string content from one encoding to another. But there are probably better migration strategies.
Going from fixed point (18 decimals) to floating point would heavily increase the complexity of the type, especially if you want to do math between types of different exponent. Not sure if that is needed. The feedback we got in CosmWasm is that everybody is happy with 18 decimal points fixed but uint128 is not sufficient for some Ethereum-related use cases. A uint256 integer with a fixed decimal point at 18 seems to make everyone happy. |
In https://github.com/cosmos/cosmjs/pull/969/files you see |
For the new SDK decimal type, my thinking was to allow users to choose what precision they do calculations with and store as an arbitrary precision string. In what use cases do people actually need a decimal value that can't fit into a uint128? That would be a very big number and I'm not sure what real world number would be that large and also require 18 decimal digits. One hacky solution could be to parse any decimal strings that contain a |
Okay, so I guess the important question is if you ever want to support math with mixed exponents. E.g. if you do
Defi stuff I understand very little about. See e.g. Decimal256 in TerraSwap. Other sane community members like @marbar3778 confirmed Decimal256 is something that is needed.
You are taking about client code consuming those things? Yeah it would be nice if the new string representation was guaranteed to have a decimal point, such that an integer cannot be the old representation and a decimal with zero fractional part at the same time. |
Hmm... I think we would just do the normal thing that GDA specifies and work with different exponents and specify a rounding precision and flags. We should require that inputs adhere to a precision limit (we do this in the regen-ledger credits module using a GDA implementation), but intermediate calculations may mix exponents depending on how the decimal library represents things. |
This is super important for clients that support backwards compatibility - being able to maintain the difference between the old type and the new type. |
@tac0turtle @aaronc Is it realistic for 0.48 to do a SDK wide state-machine-breaking migration to update all decimals to a string representation with decimal point? |
Right now, a
decimal
of typetypes.Dec
is encoded in the protobuf API asstring(int(decimal * 10**18))
orascii(string(int(decimal * 10**18)))
. While this is straight forward and efficient once you know how decimals work, it's very unintuitive if you look at the output the API gives you, such asor
In both cases the example values as well as the non-Go proto definitions do not provide hints that those are encoded decimals.
Then those decimals are sometimes encoded as strings, sometimes as bytes. E.g.
and
This hits all users that interact with the proto interface directly and do not use a higher level wrapper. Given the amount of deeply nested fields that would need wrapping, the need for custom module code generation and the desire to use reflection, this is a severe burden to DevX that will affect a lot of newcomers.
I think there needs to be a better strategy how to encode
types.Dec
at the protobuf API level. One option is using string representation with decimal points. The other option that avoids string parsing is asimilar to how Timestamp is defined.
The text was updated successfully, but these errors were encountered: