feat(chain)!: make CheckPoint data field optional#2024
feat(chain)!: make CheckPoint data field optional#2024LagginTimes wants to merge 7 commits intobitcoindevkit:masterfrom
CheckPoint data field optional#2024Conversation
cf98f58 to
eddadd4
Compare
|
Some recommended test scenarios:
With the above tests:
|
e805152 to
86968bb
Compare
e1166b6 to
46bd424
Compare
oleonardolima
left a comment
There was a problem hiding this comment.
cACK c24dd6a
It looking good code-wise, though we probably need further discussion on what's the best approach, as discussed by Evan and VM in discord.
ba55b7e to
a216494
Compare
a216494 to
ae040c2
Compare
ae040c2 to
460bc46
Compare
|
@LagginTimes please review the modifications I made to This implementation builds upon and improves the original PR's approach to optional checkpoint data in several key ways:
|
b301866 to
7ce4d91
Compare
* Base tip must always have data. * Update should be able to introduce data to a placeholder checkpoint in the original chain. * Remove unnecessary logic.
Add comprehensive tests for CheckPoint::push error cases: - Push fails when height is not greater than current - Push fails when prev_blockhash conflicts with self - Push succeeds when prev_blockhash matches - Push creates placeholder for non-contiguous heights Include tests for CheckPoint::insert conflict handling: - Insert with conflicting prev_blockhash - Insert purges conflicting tail - Insert between conflicting checkpoints 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1939dd2 to
1f62476
Compare
|
@LagginTimes I've rebased on master. Would you be okay if I took over this PR? |
Rework CheckPoint::insert to properly handle conflicts: - Split chain into base (below insert height) and tail (at/above) - Rebuild chain by pushing tail items back, handling conflicts - Displace checkpoints to placeholders when prev_blockhash conflicts - Purge orphaned checkpoints that can no longer connect to chain - Fix edge cases where placeholders weren't handled correctly Improve CheckPoint::push: - Remove trailing placeholder checkpoints before pushing - Maintain existing behavior of creating placeholders for gaps Documentation improvements: - Clarify displacement vs purging rules without complex if-else chains - Add concrete examples showing the behavior - Add inline comments explaining the complex rebuild logic Add comprehensive test coverage for displacement scenarios including inserting at new/existing heights with various conflict types.
1f62476 to
bd7a0db
Compare
| @@ -51,6 +54,7 @@ | |||
| .expect("extension is strictly greater than base"), | |||
There was a problem hiding this comment.
This expect is now wrong. A block in the extension may have a prev_blockhash that doesn't line up.
There was a problem hiding this comment.
There seems to be a lot of additional logic in LocalChain to manage ChangeSets. This is non-ideal as the mutating logic of CheckPoint is now more complex - so we really want to keep the complexity in CheckPoint only.
Instead of having apply_changeset_to_checkpoint, I'm thinking of using methods of CheckPoint directly and comparing the original and updated checkpoint chains to derive the checkpoint.
| update_tip: CheckPoint<D>, | ||
| ) -> Result<(CheckPoint<D>, ChangeSet<D>), CannotConnectError> | ||
| where | ||
| D: ToBlockHash + fmt::Debug + Copy, |
There was a problem hiding this comment.
I wonder if the + Copy here will be problematic.
|
Replaced by #2115 |
c486ba7 docs: address review feedback on `prev_blockhash` validation (志宇) 031b30f docs(core): address review feedback on docs and tests (志宇) ef35b19 fix(chain)!: make genesis immutable in `merge_chains` (志宇) d8cb41f test(core): address review feedback on checkpoint tests (志宇) 9c0453c docs(core): Add module-level docs for `checkpoint_entry` (志宇) 3ef6ed8 feat(chain)!: Add `ApplyBlockError` for `prev_blockhash` validation (志宇) bf6541b feat(chain)!: Relax the generic parameter for `LocalChain<D>` (志宇) 19b9006 test(core): add tests for CheckPoint::push and insert methods (志宇) 9971fda test(chain): Test `apply_update` with a single `CheckPoint<Header>` (valued mammal) 3df0609 test(chain): make `TestLocalChain` generic and add `prev_blockhash` test (志宇) c314b25 fix(chain): `merge_chains` now takes account of `prev_blockhash`es (志宇) f10ba0e fix(core): `Checkpoint::insert` now evicts on `prev_blockhash` mismatch (志宇) 046a771 fix(core): `push` now errors on `prev_blockhash` mismatch (志宇) 68d1ef4 feat(core): Initial work on `CheckPointEntry` (志宇) d4bdff0 feat(core): Add `prev_blockhash` method to `ToBlockHash` trait (志宇) Pull request description: Closes #2021 Related to #2076 Replaces #2024 Replaces #2091 ### Description This PR adds `prev_blockhash` awareness to `CheckPoint`, enabling proper chain validation when merging checkpoint chains that store block headers or similar data with previous block hash information. ### Notes to the reviewers This PR replaces some prior attempts: * #2024 - where we made the `CheckPoint::data` optional - however this resulted in internal complexity and an API with annoying edge cases. The tests from this PR were still useful. * #2091 - This second attempt had some good ideas, but was distracted from the goal of #2021. I mostly reused the `CheckPoint::insert` implementation of that PR. ### Changelog notice ```md Added: - `ToBlockHash::prev_blockhash()` - optional method to expose previous block hash - `CheckPointEntry` - new type for iterating with `prev_blockhash` awareness, yielding "placeholder" entries for heights inferred from `prev_blockhash` - `ApplyBlockError` - this is a new error type with two variants; `MissingGenesis` and `PrevBlockhashMismatch`. The second variant is a new error case introduced by `prev_blockhash` awareness. Changed: - `CheckPoint::push` - now errors when `prev_blockhash` conflicts with current tip (contiguous heights) - `CheckPoint::insert` - now evicts/displaces checkpoints on `prev_blockhash` conflict - `merge_chains` - now validates `prev_blockhash` consistency when merging - `LocalChain<D>` generic parameter - relaxed constraint to `D: Clone` instead of `D: Copy`. Fixed: - `merge_chains` no longer replaces the genesis block. ``` ### Checklists #### All Submissions: * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature ACKs for top commit: evanlinjin: self-ACK c486ba7 Tree-SHA512: 5622a8a418034443931c8b5938e708c2222c42c05efbdac71d47a4e0ce1b4f4b0b7bcd2e1e14e2f295cc056e12c03e5750b40b1a1313cdbdf59a009d81d0b8a1
Resolves #2021.
Description
This PR makes the
CheckPoint::datafield optional. Gaps inferred fromprev_blockhashare represented as placeholder checkpoints wheredataisNone. Subsequentinsert()s will providedatafor the placeholders when a matching block arrives.See: #2017 (comment)
Notes to the reviewers
WIP
Changelog notice
Checklists
All Submissions:
New Features:
Bugfixes: