Skip to content

units: Improve code enforcing privacy boundry#4258

Merged
apoelstra merged 2 commits intorust-bitcoin:masterfrom
tcharding:03-19-privacy-boundry
Apr 16, 2025
Merged

units: Improve code enforcing privacy boundry#4258
apoelstra merged 2 commits intorust-bitcoin:masterfrom
tcharding:03-19-privacy-boundry

Conversation

@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding commented Mar 19, 2025

This is a follow up to #4256 - onwards and upwards!

Close: #4140

@github-actions github-actions bot added C-bitcoin PRs modifying the bitcoin crate C-units PRs modifying the units crate test labels Mar 19, 2025
@apoelstra
Copy link
Copy Markdown
Member

Can rebase now.

/// represent roughly -21.47 to 21.47 BTC.
pub const fn from_sat_i32(satoshi: i32) -> SignedAmount {
SignedAmount(satoshi as i64) // cannot use i64::from in a constfn
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The reason for this is not entirely obvious but the change is correct. So to clarify: this being inside privacy boundary allows it to not have the "runtime" check (most likely optimized-away after inlining). But if we wanted to get rid of that check we should have _unchecked method instead. But we don't want that (yet), since the check here will have zero performance impact in optimized builds and it's not worth the cost of dealing with unchecked constructors to optimize debug builds.

Since you have to rebase anyway, please add it to the commit message or code comment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added to commit log.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for more explanation. is my understanding correct that:

  • Items inside encapsulate are in a privacy boundary?
  • Items inside encapsulate are not "runtime" checked.
  • moving from_sat_i32 outside of encapsulate means it is "runtime" checked?
  • Items inside the privacy boundary access the inner-field while those outside the privacy boundary do not?

Wouldn't mod private be more descriptive than mod encapsulate if items inside encapsulate are insides a "privacy boundary"? Furthermore, I'm struggling with the notion of "constructors" that are in a "privacy boundary". Looking at these concepts from the outside of those developing has left me confused, although I'm sure to those implementing it it's perfectly logical.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's not really that much related to runtime checks. It's about which methods have access to the internal field. Ideally there should be only one so that if layout changes we don't have to modify a bunch of places that relied on something specific (like it being u64 here). Realistically, there need to be at least two, sometimes four methods.

One of the arguments to put more than one function into the privacy boundary is to bypass the checks for perf reason without introducing _unchecked constructor. This code move is about that argument being invalid here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see now what the motivation is here, and that SignedAmount(satoshi as i64) is only usable inside the encapulate namespace. Reducing the reliance on the inner field would make changes and refactor less noisy.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's also the part about not breaking invariant by accident. Basically, to make sure nothing breaks the invariant we only have to audit the submodule and nothing else. That makes code review much easier.

@tcharding tcharding force-pushed the 03-19-privacy-boundry branch from bc2d154 to 6ca5f40 Compare March 20, 2025 21:45
@github-actions github-actions bot removed C-bitcoin PRs modifying the bitcoin crate test labels Mar 20, 2025
@tcharding tcharding marked this pull request as ready for review March 20, 2025 21:45
@tcharding tcharding force-pushed the 03-19-privacy-boundry branch from 6ca5f40 to 3909aa2 Compare March 20, 2025 22:14
Kixunil
Kixunil previously approved these changes Mar 21, 2025
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK 3909aa2

@tcharding
Copy link
Copy Markdown
Member Author

Note please I added the Close #4140 line to the PR description after ack was given.

apoelstra
apoelstra previously approved these changes Mar 25, 2025
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 3909aa2; successfully ran local tests

@apoelstra
Copy link
Copy Markdown
Member

Needs rebase

Recently I wrote a panic message that included the maximum value of an
integer however I used the max of a 16 bit value for both signed and
unsigned - this is incorrect.

Use the correct values for `u16::MAX` and `i16::MAX`.
@tcharding tcharding dismissed stale reviews from apoelstra and Kixunil via 29a8115 April 3, 2025 02:01
@tcharding tcharding force-pushed the 03-19-privacy-boundry branch from 3909aa2 to 29a8115 Compare April 3, 2025 02:01
From my reading of the new sanity rules (rust-bitcoin#4090) we should only have a
single constructor that accesses the inner field of the amount types.

Furthermore we have one const constructor inside the privacy boundry and
a couple outside.

Move the const constructors outside of the privacy boundry.

Internal change only.

Please note

The function being inside privacy boundary allows it to not have the
"runtime" check (most likely optimized-away after inlining). But if we
wanted to get rid of that check we should have _unchecked method
instead. But we don't want that (yet), since the check here will have
zero performance impact in optimized builds and it's not worth the
cost of dealing with unchecked constructors to optimize debug builds.
@tcharding tcharding force-pushed the 03-19-privacy-boundry branch from 29a8115 to ca6c607 Compare April 3, 2025 02:10
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 ca6c607; successfully ran local tests

@apoelstra
Copy link
Copy Markdown
Member

cc @Kixunil could you re-ack this? The rebase is nontrivial (I mean, it's conceptually trivial but there is still a bunch of stuff in the range-diff.)

@tcharding
Copy link
Copy Markdown
Member Author

Merge please.

@apoelstra apoelstra merged commit b473a20 into rust-bitcoin:master Apr 16, 2025
24 checks passed
@tcharding tcharding deleted the 03-19-privacy-boundry branch April 28, 2025 03:37
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.

units: Make amount follow sanity rules

4 participants