Commit Graph

203 Commits

Author SHA1 Message Date
merge-script b473a2090a
Merge rust-bitcoin/rust-bitcoin#4258: units: Improve code enforcing privacy boundry
ca6c607953 Adhere to sanity rules for amount types (Tobin C. Harding)
6c614d9320 units: Fix panic message (Tobin C. Harding)

Pull request description:

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

  - Patch 1: Fix the incorrect BTC value in panic message
  - Patch 2: Strictly adhere to the sanity rules (#4090)

   Close: #4140

ACKs for top commit:
  apoelstra:
    ACK ca6c607953c03aa2dc168f58329681d9e69eee04; successfully ran local tests

Tree-SHA512: 6d7fd60830e1a0f6d6262ab02ec6e297b095d0fe8fb7737563979652e4a3b4a9477a79982201c42b08e2555fd23dc5c430549966b534bdf45f40621ae81da83a
2025-04-16 18:33:09 +00:00
yancy 812c21e2e4 refactor: Replace fold with try_fold
The and_then combinator performs a kind of bitwise and operation on two
Option types here.  This is useful since the `checked` arithmetic
returns an option thereby accumulating Option types.  Therefore, either
the checked arithmetic operation performs the addition of the unwrapped
accumulator, or it returns None.

Instead of using `and_then` use the provided `try_fold` method which
will short circuit on `None` when the checked arithmetic is used.  Also,
simplify the staring condition using `Amount:ZERO` since this is
logically equivalent to using the first value if one exists.

Lastly, by using the built in `try_fold`, it's possible the performance
will be improved by making use of the short circuit ability instead of
evaluating each item even when the accumulator holds a None type.
2025-04-15 08:21:11 -05:00
Jamil Lambert, PhD ec38860b65
Add a test to kill mutants in MathOp
Weekly mutation testing found mutants in `is_overflow` and
`is_divide_by_zero`.

Add a test to kill them.
2025-04-11 09:31:13 +01:00
Tobin C. Harding d6881ff5f8
units: Enable differentiating div-by-zero
Division by zero is a different error class that overflow. Add a
`MathOp` enum that enables one to check the error class.
2025-04-08 09:04:30 +10:00
Tobin C. Harding 5fb64953c5
units: Return NumOpResult when implementing Div
Currently we use a std numeric type for the output of various `Div`
implementations while other ops use `NumOpResult`. This makes it
difficult to chain operations.

Throughout the crate use `Output = NumOpResult<Foo>` when implementing
`Div`.

Later we want to enable users differentiating between an overflow and a
div-by-zero. Explicitly do not implement that yet, done separately to
assist review.
2025-04-07 15:08:01 +10:00
Tobin C. Harding f5b54e5fe0
units: Move general result stuff to a separate module
We currently use the `NumOpResult` for operations involving more than
just amount types (e.g. `FeeRate`) however when the `result` module was
written we only used amount types.

To make the intention of the custom result types more clear introduce a
top level `result` module and move the general code there. Leave the
amount implementations in the `amount` module. Note that both `result`
modules are private.

Move the `OptionExt` impls because later we will add a bunch more of them.

Internal change only, no logic changes.
2025-04-07 12:14:09 +10:00
Tobin C. Harding f49efdf3f7
units: Remove mention of amount in result module
We currently use the `NumOpResult` for operations involving more than
just amount types (e.g. `FeeRate`) however when the `result` module was
written we only used amount types.

To make the docs and code clearer use 'numeric type' instead of
'amount' in docs. And for local variables use `x` instead of `amount`.

This is docs and internal changes only.
2025-04-07 12:13:45 +10:00
Tobin C. Harding ca6c607953
Adhere to sanity rules for amount types
From my reading of the new sanity rules (#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.
2025-04-03 13:09:40 +11:00
Tobin C. Harding 6c614d9320
units: Fix panic message
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`.
2025-04-03 12:58:30 +11:00
merge-script 59524adafd
Merge rust-bitcoin/rust-bitcoin#4295: Automated nightly rustfmt (2025-03-30)
b8910e201e 2025-03-30 automated rustfmt nightly (Fmt Bot)

Pull request description:

  Automated nightly `rustfmt` changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

ACKs for top commit:
  apoelstra:
    ACK b8910e201ea4374bb0508aa50c6779d080ef6484; successfully ran local tests

Tree-SHA512: 9bd89439304322d30e04aae8f9803f9e07830b616cb49339ac4b1e0ee1bfe440865d9ebc7f41eea1bcd35cb751060215eec20d258d88e9f20dd3f905b9ab690f
2025-03-30 19:37:31 +00:00
merge-script f2869ad348
Merge rust-bitcoin/rust-bitcoin#4292: chore: fix grammatical errors
6ebdf61e76 Fix grammatical typos (VolodymyrBg)

Pull request description:

  base58/src/error.rs:

  - Corrected grammar in error comment: "Found a invalid ASCII byte" → "Found an invalid ASCII byte".

  bitcoin/CHANGELOG.md:

  - Fixed typo in function name: p2wpkh_signiture_hash → p2wpkh_signature_hash.

  units/src/amount/error.rs:

  - Fixed grammar: "was large than" → "was larger than".

  units/src/fee_rate/mod.rs:

  - Corrected typo: "assoctiated" → "associated".

  units/tests/api.rs:

  - Grammar fix: "THE POINT of tests are" → "THE POINT of tests is".

ACKs for top commit:
  apoelstra:
    ACK 6ebdf61e769903da1ad21fd6ab9bf22ff3c04bab; successfully ran local tests

Tree-SHA512: bb5800b6248bedad46d511a0123c50b1d8d2deacfa752cd675d21e40cb78a6a5d917da28a9a87c3f779cd13819d5b16a7668d1e388d1d58d200ea688d8c114ac
2025-03-30 15:19:49 +00:00
Fmt Bot b8910e201e 2025-03-30 automated rustfmt nightly 2025-03-30 01:27:51 +00:00
VolodymyrBg 6ebdf61e76 Fix grammatical typos
Fix grammar and typos in documentation and README
2025-03-27 20:49:19 +02:00
Jamil Lambert, PhD 9a2b56f381
Modify test in Amount to kill mutants
Mutants found in weekly mutation testing.

Add an assert for both signed and unsigned to an existing test to kill
them.
2025-03-26 09:48:21 +00:00
Erick Cestari e744347022 Make usage of Self and type uniform across both modules
This commit standardizes the function signatures in the Amount and SignedAmount
implementations by consistently using Self as the return type instead of the concrete
type names. This makes the code more consistent, easier to maintain, and follows Rust's
idiomatic practices.

Changes:

Replace all occurrences of -> Amount with -> Self in unsigned.rs
Replace all occurrences of -> SignedAmount with -> Self in signed.rs
Make similar replacements for Option/Result return types
Use Self:: instead of the explicit type name for static method calls
2025-03-21 14:26:35 -03:00
Andrew Poelstra 2958521117
amount: remove from_sat_unchecked
Turns out we don't even need this. It is only used in one place now and
we can just stick an .expect there.
2025-03-18 19:33:03 +00:00
Andrew Poelstra d0d7a15604
amount: move MIN/MAX constants and constructors inside the privacy boundary
It's conceptually a bit tortured to have an `Amount` type defined in a
private module, with an _unchecked method allowing you to set values out
of range, which needs to be used outside of the module to *define* the
range and the constructors that check it.

Move the constants and constructors inside the privacy module, where they
can be written directly. This is easier to understand and eliminates a couple
_unchecked calls.
2025-03-18 19:33:03 +00:00
Andrew Poelstra 004d073184
amount: return i64 from parse_signed_to_satoshi
This private function is used for string-parsing an amount. It returns a
sign boolean and a u64, but its surrounding logic can be simplified if
it just returns a i64 (which is OK now since the range of `Amount` fits
into the range of i64).

Along the way we eliminate some instances of from_sat_unchecked.

Annoyingly we still need the bool to distinguish -0 from +0; when
parsing Amount we reject -0 (and we have tests for this).

This causes a couple error constructors to no longer be used outside of
unit tests. May be worth looking at whether we need them, or whether we
should be using them in parse_signed_to_satoshi.
2025-03-18 19:32:58 +00:00
Andrew Poelstra 3370c14d74
amount: stop using from_sat_unchecked in tests
There is no need for this. It's a 2-line diff to change it.
2025-03-18 19:27:54 +00:00
Andrew Poelstra beaa2db7e5
amount: add from_sat_i32 and from_sat_u32 methods for small constants
We have a ton of calls to `from_sat_unchecked` for small constants which
were clearly in range, e.g. in fee.rs. Add a new constfn for these
cases. Don't bother making a generic Into<u32>/Into<u16> variant because
there isn't an obvious name for it.

There are 7 instances where we're using this method with values that are
out of range, which we leave as from_sat_unchecked for now.
2025-03-18 19:27:53 +00:00
Andrew Poelstra 82d9d1aeea
amount: rename `from_int_btc_const` unctions to hungarian ones
We have `from_int_btc_const` on both `Amount` and `SignedAmount` because
the "real" `from_int_btc` is generic over the integer type it accepts,
which means that it cannot be a constfn. But we do want a constfn.

However, just because `from_int_btc_const` exists for the sake of
constfn doesn't mean that that's what it *is*. So rename these methods
to reflect what they *are*.
2025-03-18 19:27:51 +00:00
Tobin C. Harding 2ec1c2a044
units: Make from_int_btc_const take a 16 bit integer
The `from_int_btc_const` constructors are specifically designed for
easily creating amount types in const context but currently they return
an error which is annoying to handle in const context. If we make the
`whole_bitcoin` parameter a 16 bit integer this gives us a nicer const
constructor with the downside that it can only create values upto a
maximum of

- unsigned: 65_536
- signed: 32_767

That is plenty high enough for most use cases.

Then use the new `from_int_btc_const` in associated consts.

Note that because `from_sat` checks max (and min) values we must
define max and min from sats directly.
2025-03-18 14:49:34 +00:00
Fmt Bot a74e08a53d 2025-03-16 automated rustfmt nightly 2025-03-16 01:25:25 +00:00
Tobin C. Harding ab4ea7c13d
Enforce the MAX_MONEY invariant in amount types
Enforcing the MAX_MONEY invariant is quite involved because it means
multiple things:

- Constructing amounts is now fallible
- Converting from unsigned to signed is now infallible
- Taking the absolute value is now infallible
- Integer overflow is illuminated in various places

Details:

- Update from_sat to check the invariant
- Fix all docs including examples
- Use the unchecked constructor in test code
- Comment any other use of the unchecked constructor
- Deprecate unchecked_abs
- Fail serde (using the horrible string error variant)
- Try not to use the unchecked constructor in rustdocs, no need to encourage unsuspecting users to use it.
- Use ? in rustdoc examples (required by Rust API guidlines)
- Remove TryFrom<Amount> for SignedAmount because the conversion is now infallible. Add a From impl.
- Fix the arbitrary impls
- Maintain correct formatting
- Remove private check_max function as its no longer needed
2025-03-13 09:07:14 +11:00
Tobin C. Harding 5d851f1c3e
Remove deprecated amount methods
When we enforce the MAX_MONEY invariant these functions would require
the function signature changing - might as well just delete them.
2025-03-11 05:37:40 +11:00
Tobin C. Harding 76a2d70b28
Make mul weight by fee return NumOpResult
Now that we have the `NumOpResult<Amount>` type that is used to show a
math calculation returned a valid amount we can use it when multiplying
weight and fee rates thus removing panics.
2025-03-11 05:37:40 +11:00
Tobin C. Harding 13595fbe7d
Fix amount whole bitcoin constructors
I royally botched the recent effort to make const amount constructors
use a smaller type. I left in an  unnecessary panic and forgot to do
both of them.

Note these function return values will change again very shortly when we
start enforcing the MAX_MONEY invariant. However the 64 to 32 bit change
is unrelated to that and is easier to review if done separately.

Whole bitcoin can not in any sane environment be greater than 21,000,000
which fits in 32 bits so we can take a 32 bit integer in the whole
bitcoin constructors without loss of utility. Doing so removes the
potential panic.

This is a breaking API change. We elect not to deprecate because we want
to keep the same function names.
2025-03-11 05:37:40 +11:00
Tobin C. Harding ac71680202
Pick one - MAX or MAX_MONEY
Just use MAX everywhere in this codebase.

After discussion in PR consensus was to just use MAX throughout the
codebase.

ref: https://github.com/rust-bitcoin/rust-bitcoin/pull/4164#discussion_r1979441438
2025-03-11 05:37:39 +11:00
Tobin C. Harding 6d70c77cf9
Enforce newtype sanity rules for amount types
The unchecked-should-be-unsafe conversation is out of scope for this
patch. We want to bite off small chunks so the constructors are left as
they currently are - we are just doing the encapsulation here. This is
in preparation for enforcing the MAX_MONEY invariant which is not
currently enforced.

As per the sanity rules policy outline in:

 https://github.com/rust-bitcoin/rust-bitcoin/discussions/4090

For both amount types create a private `encapsulate` module that
consists of exactly the type and a single constructor and a single
getter.
2025-03-11 05:37:19 +11:00
Tobin C. Harding e6f7b26d80
Use _unchecked in amount const types
We are about to start enforcing the MAX_MONEY invariant. Doing so will
change constructors to return an error type.

In preparation use the `_unchecked` constructor for all the consts.

Internal change only, no logic changes.
2025-03-11 05:32:07 +11:00
Andrew Poelstra ef0af8d62e
Use sat/ssat constructors throughout tests
There is an as yet unresolved discussion about the unchecked amount
constructor. In an effort to focus the amount of changes required later
and also to make the `tests` module uniform use the `sat` and `ssat`
constructor functions everywhere.

Internal change only, no logic changes.
2025-03-11 05:32:06 +11:00
Tobin C. Harding 8ecdc7c275
Use den_ prefix for local Denomination variable
Throughout the `amount::tests` module we use `sat` and `ssat` as aliases
to amount constructors but in on test we use them as `Denomination`
variables. To assist clarity and so we can introduce uniform usage of
the constructor aliases change the variable names to use the `den_`
prefix.

Internal change only, no logic changes.
2025-03-11 05:32:06 +11:00
yancy a273814d23 Replace underflow with overflow in doc comments
The use of underflow is misleading.  Adding one to MAX and
subtracting one from MIN are both considered an overflow.
2025-03-08 10:41:20 -06:00
yancy 2f897e2109 Remove warning section
Since monadic handling has been introduced, panics have been replaced
with return errors.  Therefore this section is no longer applicable.
2025-03-08 10:41:20 -06:00
merge-script 86266d2dad
Merge rust-bitcoin/rust-bitcoin#4161: Improve ops for amount types
0a9f14f7b0 Implement Div by amount for amount types (Tobin C. Harding)
b57bfb9bc5 Add missing Mul impls for amount types (Tobin C. Harding)
501c9ab89e Test amount ops that involve an integer (Tobin C. Harding)
851080d3b1 Add more add/sub tests (Tobin C. Harding)
47923957b1 Improve add/sub tests for amount types (Tobin C. Harding)
8bb9ce3e47 Add tests for amount op int (Tobin C. Harding)

Pull request description:

  Improve the test coverage and add missing implementations of math operations for the amount types.

  Along the way close #4030.

ACKs for top commit:
  apoelstra:
    ACK 0a9f14f7b036c5232449d058fb6d425c8376d87a; successfully ran local tests; nice!

Tree-SHA512: f303b2a90b5bb9e77091e047f8325821a5c89f52dfe242d849968dba0d097d3868d444009c2c05b9d7c0e91fa2ce6898cdc4733977699ca4b1ae226562878cdf
2025-03-08 15:12:51 +00:00
merge-script 1a18ff582c
Merge rust-bitcoin/rust-bitcoin#4127: units: Prevent casting pub enums as ints
97453ef9bc units: Prevent casting pub enums as ints (Tobin C. Harding)

Pull request description:

  A public enum with simple variants gets an automatic integer variant that can be cast by library consumers. This puts a unnecessary maintenance burden upon us because we cannot then add variants in the middle of others.

  Add a hidden variant to the single public non-error enum in `units`.

ACKs for top commit:
  Kixunil:
    ACK 97453ef9bc
  apoelstra:
    ACK 97453ef9bc2b99a67252419ff015f13679df7312; successfully ran local tests

Tree-SHA512: 2515152107fb21a2dbdef9b46308fef6bd45f4a9719da7a39149b3bdbce6a93dc0f98e112ac246eb32dbe4df1210d5e6328c26ea8678e3da15276e893b39cc9c
2025-03-07 17:32:54 +00:00
Tobin C. Harding 97453ef9bc
units: Prevent casting pub enums as ints
A public enum with simple variants gets an automatic integer variant
that can be cast by library consumers. This puts a unnecessary
maintenance burden upon us because we cannot then add variants in the
middle of others.

Add a hidden variant to the single public non-error enum in `units`.
2025-03-06 11:34:02 +11:00
Shing Him Ng 90d909becc Kill mutants in primitives and units
This kills 15 mutants found with the mutants workflow
2025-03-04 21:35:10 -06:00
Tobin C. Harding 0a9f14f7b0
Implement Div by amount for amount types
It is semantically valid to divide an amount by another amount. The
result of the operation is an integer.

Note that we cannot implement `Div` by `NumOpResult` because there is no
way to show the div by invalid case.

Implement `Div` by amount for both amount types.
2025-03-03 08:12:41 +11:00
Tobin C. Harding b57bfb9bc5
Add missing Mul impls for amount types
Add and test missing `Mul` impls for both amount types.
2025-03-03 08:12:41 +11:00
Tobin C. Harding 501c9ab89e
Test amount ops that involve an integer
From the amount types `Div`, `Mul`, and `Rem` can have an integer on one
side. Test them - includes commented out test for one missing combo.
2025-03-03 08:12:41 +11:00
Tobin C. Harding 851080d3b1
Add more add/sub tests
Add units tests for various values including negative values.
2025-03-03 08:12:40 +11:00
Tobin C. Harding 47923957b1
Improve add/sub tests for amount types
Add a few macros to test `Add` and `Sub` impls for both amount types,
all combos of type and res (eg `Amount` and `NumOpResult<Amount>`), and
all combos of references.
2025-03-03 07:26:00 +11:00
Tobin C. Harding 8bb9ce3e47
Add tests for amount op int
We aim to support three ops on amount types that use an integer for the
right hand size. Prove that implement them.
2025-03-03 05:20:38 +11:00
kilavvy 1d2de62e01
Update mod.rs 2025-02-28 12:34:21 +01:00
looklose ce19d40a80 chore: fix some typos in comments
Signed-off-by: looklose <shishuaiqun@yeah.net>
2025-02-28 17:55:31 +08:00
Tobin C. Harding 814685e551
Macroise the NumOpResult tests
Macroise the tests improving coverage along the way.

Includes a TODO to remind us to do `Neg` more fully.
2025-02-25 20:46:01 +00:00
Andrew Poelstra a44a9d31f6
Add a few impls to the result macro
Add a few missing impls to the `impl_op_for_references` macro.

Includes a minor whitespace change so that traits are grouped together.
2025-02-25 20:45:56 +00:00
Andrew Poelstra 353c23fa01
units: pull generic op impls on NumOpResult into macro 2025-02-25 20:44:30 +00:00
Andrew Poelstra 21ac5aefe0
units: extend op reference macro to handle generics and where clauses
This is a bit ugly and requires that we put our where-clauses in
parentheses because the macro_rules parser sucks, but it allows us to
move the blanket-impls on NumOpResult into the macro.

This commit moves one instance and updates the macro; the next commits
will change the rest.
2025-02-25 20:31:45 +00:00