Skip to content

Improve lock times - fix off-by-one bug - #4468

Merged
apoelstra merged 8 commits into
rust-bitcoin:masterfrom
tcharding:05-08-locktimes
May 31, 2025
Merged

Improve lock times - fix off-by-one bug#4468
apoelstra merged 8 commits into
rust-bitcoin:masterfrom
tcharding:05-08-locktimes

Conversation

@tcharding

@tcharding tcharding commented May 8, 2025

Copy link
Copy Markdown
Member

Make the APIs uniform in relative and absolute locktimes in relation to the is_satisfied_by functions. In doing so improve the API and fix an off-by-one bug when checking satisfaction of locks by height.

Done in three patches but maybe should be squashed? Probably easiest to review by looking at all the is_satisfied_by* functions and convincing yourself we got it right.

EDIT: Now has 5 cleanup patches also (mostly docs cleanups).

@github-actions github-actions Bot added C-bitcoin PRs modifying the bitcoin crate C-units PRs modifying the units crate test C-primitives labels May 8, 2025
@github-actions

github-actions Bot commented May 8, 2025

Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@github-actions github-actions Bot added the API break This PR requires a version bump for the next release label May 8, 2025
@github-actions

github-actions Bot commented May 8, 2025

Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@apoelstra

Copy link
Copy Markdown
Member

Nice. I believe this is correct.

@tcharding

Copy link
Copy Markdown
Member Author

Mad, thanks.

@github-actions

github-actions Bot commented May 9, 2025

Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@tcharding tcharding changed the title More locktime fun primitives: Improve/fix relative lock times May 9, 2025
@github-actions

github-actions Bot commented May 9, 2025

Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@github-actions

github-actions Bot commented May 9, 2025

Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@tcharding
tcharding marked this pull request as ready for review May 9, 2025 21:59
@github-actions github-actions Bot removed the test label May 9, 2025
@github-actions github-actions Bot added the test label May 9, 2025
@tcharding tcharding changed the title primitives: Improve/fix relative lock times primitives: Improve/fix lock times - off-by-one bug May 12, 2025
@tcharding tcharding changed the title primitives: Improve/fix lock times - off-by-one bug Improve/fix lock times - off-by-one bug May 12, 2025
tcharding added 2 commits May 12, 2025 12:16
We recently improved the relative locktime function `is_satisfied_by` by
adding mined at and chain tip. We can now do the same for the
height/time satisfaction functions.

Note I believe these functions should still be provided because a user
may for some reason have either blocktime data or height data and not
have the other.

Requires some work to the errors, elect to just remove the original
field that held the function argument.

For now remove the examples in rustdocs, we can circle back to these
once the dust settles.
Define 'is satisfied by' - this is a classic off-by-one problem, if a
relative lock is satisfied does that mean it can go in this block or the
next? Its most useful if it means 'it can go in the next' and this is
how relative height and MTP are used in Core.

Ramifications:

- When checking a time based lock we check against the chain tip MTP,
then when Core verifies a block with the output in it it uses the
previous block (and this is still the chain tip).
- When checking a height base lock we check against chain tip height + 1
because Core checks against height of the block being verified.

Additionally we currently have a false negative in the satisfaction
functions when the `crate` type (height or MTP) is to big to fit in a
u16 - in this case we should return true not false because a value too
big definitely is > the lock value.

One final API paper cut - currently if the caller puts the args in the
wrong order they get a false negative instead of an error.

Fix all this by making the satisfaction functions return errors, update
the docs to explicitly define 'satisfaction'.

For now remove the examples in rustdocs, we can circle back to these
once the dust settles.

API test of Errors:

Some of the errors are being 'API tested' tested in `primitives` but
they should be being done in `units/tests/api.rs` - put all the new
errors in the correct places.
@tcharding

Copy link
Copy Markdown
Member Author

I've rolled #4486 into this PR, I think it makes more sense to review it all at once.

@tcharding tcharding changed the title Improve/fix lock times - off-by-one bug Improve lock times - fix off-by-one bug May 12, 2025
tcharding added 6 commits May 12, 2025 12:30
When checking a locktime against block height we add 1 because when the
next block is being validated that is what the height will be and
`is_satisfied_by` is defined to return true if a transaction with this
locktime can be included in the next block.

As we have in `relative`, and for the same reasons, add an API to the
absolute `Height` and `MedianTimePast`: `is_satisfied_by`. Also add
`is_satisfied_by_{height, time}` variants to `absolute::LockTime`.
Call through to the new functions in `units`.
Use lock-by-time and lock-by-height instead of lock-by-blocktime and
lock-by-blockheight respectively with no loss of clarity.
Use the new function and not the deprecated on in rustdcos and tests.
Move the `_by_{height,time}` functions to be underneath the
`is_satisfied_by` function.

Code move only, no logic change.
Slightly improve grammar and fix column width to 100.
`units::locktime::relative::Height` type is now deprecated, use the new
name in rustdoc.
@tcharding

Copy link
Copy Markdown
Member Author

I just threw 5 extra patches on top of this. They are all clean ups and I'm working on the assumption that you will not review the diff as much as the final state of the locktime modules. These cleanups should help the effort.

@tcharding tcharding added the P-high High priority label May 12, 2025
@tcharding

Copy link
Copy Markdown
Member Author

Setting locktime and fee rate work as top priority ATM. Locktimes are looking pretty good after this is merge IMO.

@tcharding

Copy link
Copy Markdown
Member Author

Bump please. This and the fee rate stuff are the final remaining pieces before we can release the units 1.0-alpha.

@apoelstra

Copy link
Copy Markdown
Member

Nice. Will ACK and merge. I am torn between "user mixes up current and confirmed blocktime" being a panic or a result. I guess if it's a result the user has the choice to either do .unwrap() to get panicking behavior, to do .unwrap_or(false) to get the existing behavior, or doing an explicit match.

The business with internally adding +1s in places also feels weird but I think it's the right thing to do.

@apoelstra apoelstra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ACK 4ccecf5; successfully ran local tests

@apoelstra
apoelstra merged commit 6d8299e into rust-bitcoin:master May 31, 2025
@tcharding
tcharding deleted the 05-08-locktimes branch June 18, 2025 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API break This PR requires a version bump for the next release C-bitcoin PRs modifying the bitcoin crate C-primitives C-units PRs modifying the units crate P-high High priority test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants