Skip to content

Enforce displaying Amount with trailing zeros#2604

Merged
apoelstra merged 1 commit intorust-bitcoin:masterfrom
448-OG:amount_8decimal_precision
Mar 17, 2024
Merged

Enforce displaying Amount with trailing zeros#2604
apoelstra merged 1 commit intorust-bitcoin:masterfrom
448-OG:amount_8decimal_precision

Conversation

@448-OG
Copy link
Copy Markdown
Contributor

@448-OG 448-OG commented Mar 16, 2024

It is common to display bitcoins using trailing zeros upto 8 decimals. This commit enforces:

  • Displaying Amount in BTC with trailing zeroes by eight decimal places if a precision on the Amount is not specified.
  • Displaying Amount in BTC upto the precision specified truncating the insignificant zeros.
  • Displaying amount in BTC without any decimals if the remainder of the amount divided by the satoshis in 1 BTC is equal to zero using formula satoshis.rem_euclid(Amount::ONE_BTC.to_sat()) != 0

These are not breaking changes and all previous tests pass.

A testcase is added to for changes introduced.

Resolves: #2136

@github-actions github-actions bot added the C-units PRs modifying the units crate label Mar 16, 2024
@coveralls
Copy link
Copy Markdown

coveralls commented Mar 16, 2024

Pull Request Test Coverage Report for Build 8316149718

Details

  • 37 of 37 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 83.927%

Totals Coverage Status
Change from base Build 8307227520: 0.02%
Covered Lines: 19732
Relevant Lines: 23511

💛 - Coveralls

@apoelstra
Copy link
Copy Markdown
Member

The CI failure is real -- you're introducing a dependence on alloc in the fmt method that didn't used to be there.

In principle we shouldn't need one.

Interestingly my local CI passes -- so we've found a blind spot in it! Let me investigate..

@apoelstra
Copy link
Copy Markdown
Member

Oh, lol, the blind spot is the entire units crate. Oops. This may also explain another "how did this get past CI?" situation last week..

@sanket1729
Copy link
Copy Markdown
Member

I forgot what our consensus was about respecting FromStr and Display invariant? Do we make an effort to maintain it?

@448-OG
Copy link
Copy Markdown
Contributor Author

448-OG commented Mar 17, 2024

The CI failure is real -- you're introducing a dependence on alloc in the fmt method that didn't used to be there.

In principle we shouldn't need one.

Interestingly my local CI passes -- so we've found a blind spot in it! Let me investigate..

Yeah! Realized it was an issue with allocation but I was not able to make changes yesterday. Should be fixed now.

My tests also passed locally. Not sure why

@448-OG
Copy link
Copy Markdown
Contributor Author

448-OG commented Mar 17, 2024

What is the current policy on running rustfmt, my editor does auto format but when I do a diff I see so many changes related to formatting

@448-OG
Copy link
Copy Markdown
Contributor Author

448-OG commented Mar 17, 2024

So I also need to fix it for tests, somehow they succeed locally

@apoelstra
Copy link
Copy Markdown
Member

What is the current policy on running rustfmt, my editor does auto format but when I do a diff I see so many changes related to formatting

Please do not commit unrelated changes. Usually there should not be very many because we have a weekly bot which does all the formatting changes, but lately we have been skipping the bot because one mantainer claims undue difficulty in rebasing.

So you will need to override your editor or be careful about what changes you commit, for now.

@apoelstra
Copy link
Copy Markdown
Member

I forgot what our consensus was about respecting FromStr and Display invariant? Do we make an effort to maintain it?

Yes, we "make an effort". But there are some exceptional cases, most notably Script, and I don't think we've worked out an explicit policy.

@sanket1729
Copy link
Copy Markdown
Member

@448-OG, you can use just format that would internally use the nightly formatter. In your editor is vscode, you can configure project specific settings for rust-bitcoin and set the formatter as just format

It is common to display bitcoins using trailing zeros upto 8 decimals.
This commit enforces:
- Displaying Amount in BTC with trailing zeroes by eight decimal places
  if a precision on the Amount is not specified.
- Displaying Amount in BTC upto the precision specified truncating the insignificant zeros.
- Displaying amount in BTC without any decimals if the remainder of the amount
  divided by the satoshis in 1 BTC is equal to zero using formula `satoshis.rem_euclid(Amount::ONE_BTC.to_sat()) != 0`

These are not breaking changes and all previous tests pass.

A testcase is added to for changes introduced.

Resolves: #2136
Copy link
Copy Markdown
Member

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

ACK d887423

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK d887423

@apoelstra apoelstra merged commit 93ca42c into rust-bitcoin:master Mar 17, 2024
@448-OG 448-OG deleted the amount_8decimal_precision branch March 17, 2024 20:49
@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 2, 2024

WTF, this PR reversed what was previously intentionally changed for a good reason in #716

Honestly, I'm starting to get annoyed by people changing intentional design without a proper justification. In this case part of the problem is my fault for not including a test. Good learning experience for me, I'll definitely do better.

It is common to display bitcoins using trailing zeros upto 8 decimals.

This is bad justification because people can just use {:.8} if they want that but minimal formatting is impossible to specify. Therefore this was a breaking change.

@apoelstra
Copy link
Copy Markdown
Member

@Kixunil if you want specific behavior from the amount display traits then you need tests and very specific comments. Because this module is insanely complicated and we have had multiple complaints about it and it's impossible to tell what is "deliberate" and what is not.

I note that this claims to fix a linked bug where you replied "definitely a bug", and then alongside your comment here you commented on that issue suggesting a completely undiscoverable workaround. The linked issue also definitely is a bug because it involves Amount treating formatters differently than f64s.

Further, I don't even know what specifically you're complaining about. You say you "intentionally changed for a good reason" ...some specific aspect of formatting in a PR whose description is a "significant refactor" that "makes Amount configurable"?

In general I appreciate you retroactively reviewing PRs like this, because it lets us move forward and then double-back to fix oversights rather than having half a dozen perma-stalled PRs that prevent everyone else from rebasing. But in this case I have no idea what you're talking about.

Kixunil added a commit to Kixunil/rust-bitcoin that referenced this pull request Jul 2, 2024
Displaying with minimal number of zeros is the default in Rust and we
want to follow it. This was originally implemented in rust-bitcoin#716 but rust-bitcoin#2604
reversed it claiming this is common, however it broke people who rely on
minimal display (e.g. BIP21) without fixing the root cause of rust-bitcoin#2136.

This reverts commit d887423 adds a test
to prevent this change and also fixes the problem with `{:0.8}` not
working.

Closes rust-bitcoin#2136
Closes rust-bitcoin#2948
@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 2, 2024

The PR literally states:

Further, this makes all representations of numbers minimal by default,
so should be documented as a possibly-breaking change.

Though it doesn't provide justification. The justification is in #709 (which is linked).

I think we should have a proptest checking roughly that format!("{:$params}", amount.display_in(denom)) == format!("{:$params}", amount.to_sat() as f64 * 10f64.pow(denom.precision())) for any params, amount and denom.

@apoelstra
Copy link
Copy Markdown
Member

If you can write that proptest properly I'd be thrilled. I tried doing this (as a fuzztest, not as a proptest) but I got constantly gummed up by the width parameter which behaves weirdly because of the denomination. I'm not even certain how it should behave -- does the denomination's width count against the width of the output?

This should probably be promoted to its own issue. I really would like this fuzztest to exist because it would document exactly how we believe Amount should be formatted.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 2, 2024

behaves weirdly because of the denomination

To my knowledge it behaves correctly. However the proptest must not test the case with denomination (though maybe we can hack it).

I'm not even certain how it should behave

Width means total width of the field but is precision is too big it'll be wider. With denomination we have to subtract the length of denomination from available width. (There's a potential question whether it should truncate the denomination. I don't think so.)

apoelstra added a commit that referenced this pull request Jul 4, 2024
3196c27 Deprecate `Amount::fmt_value_in` (Martin Habovstiak)
467546f Round `Amount` when requested precision is too low (Martin Habovstiak)
7c95a77 Fix `Amount` decimals handling (Martin Habovstiak)

Pull request description:

  Displaying with minimal number of zeros is the default in Rust and we want to follow it. This was originally implemented in #716 but #2604 reversed it claiming this is common, however it broke people who rely on minimal display (e.g. BIP21) without fixing the root cause of #2136.

  This reverts commit d887423 adds a test to prevent this change and also fixes the problem with `{:0.8}` not working.

  Closes #2136
  Closes #2948

  Can we backport this one too?

ACKs for top commit:
  tcharding:
    ACK 3196c27
  apoelstra:
    ACK 3196c27 I also really like how this reduces the complexity of the module, basically passing everything through to `display_in`

Tree-SHA512: 3221f83086ac55af3d4caad03fe2b619be303533bba12096040419d119600c8597938809e171662f11b515d469156b083b2072b901d445e4fdfc7b1062cf7b6a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-units PRs modifying the units crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shouldn't Amount handle decimals formatting with {:.8} ?

5 participants