kernel: add block locator to the C API #34843

pull pzafonte wants to merge 1 commits into bitcoin:master from pzafonte:kernel-api-block-locator changing 4 files +142 −0
  1. pzafonte commented at 6:21 pm on March 17, 2026: none

    The block locator is the primitive a node uses to announce its chain position to peers. When a node resumes after shutting down on a stale tip, it sends its locator so a peer can identify the fork point and serve the blocks needed to reach the best chain. Without this, callers of libbitcoinkernel have no canonical way to recover from a stale tip.

    Adds three C API functions: btck_chainstate_manager_get_locator to retrieve the active tip’s locator as a btck_BlockLocator, btck_block_locator_to_bytes to serialize it, and btck_block_locator_destroy to free it.

    Includes a C++ convenience wrapper and Boost tests covering the genesis-only and post-IBD cases.

    Motivated by kernel-node/pull/30 (edit: idea for the PR came from rustaceanrob’s comment ), which needs this primitive to implement sync recovery in a Rust consumer of libbitcoinkernel.

  2. DrahtBot added the label Validation on Mar 17, 2026
  3. DrahtBot commented at 6:21 pm on March 17, 2026: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept NACK stickies-v

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33796 (kernel: Expose CheckTransaction consensus validation function by w0xlt)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    LLM Linter (✨ experimental)

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • std::memcpy(hash.data(), b.data() + 5 + i * 32, 32) in src/test/kernel/test_kernel.cpp

    2026-03-18 06:50:01

  4. stickies-v commented at 8:01 pm on March 17, 2026: contributor

    I’m not convinced this would be a good addition to the kernel interface.

    Without this, callers of libbitcoinkernel have no canonical way to recover from a stale tip.

    Why can’t kernel users construct their own locator by reverse iterating from the stale tip using any logic they want to? I don’t think there is or should be a canonical way to do so? The way Bitcoin Core implements how they get filled should in my view just be an implementation detail?

    edit: I do think we need to improve the interface to make it easier to efficiently build a locator performantly. I would love to generalize btck_chain_get_by_height to work on any chain (including a stale tip), and not just the currently active chain.

  5. sedited commented at 9:14 pm on March 17, 2026: contributor

    Looking this over briefly, this still needs work. If we expose locators, we should expose their primitive, not just a list of block hashes. The API could be pretty simple in that case: Just a create, destroy, and to bytes function.

    I agree that locators can generally be seen as an implementation detail. However I’d like to advocate in their favor a bit. We do have a function that finds forks with block locators (FindForkInGlobalIndex) and I wonder if all clients implementing that might be a source of bugs. I think adding them would be mostly harmless, they have very narrow scope, and every external client using the kernel needs to implement them in order to use the network, so I’d expect them to be useful.

  6. kernel: add btck_chainstate_manager_get_locator
    A block locator is the primitive a node uses to announce its chain
    position to peers. Exposing it lets callers recover from a stale-tip
    shutdown by sending their locator so a peer can identify the fork
    point and serve the missing blocks.
    
    Exposes btck_BlockLocator as an opaque type with create/destroy/to_bytes
    functions
    
    Re-uses GetLocator(tip) from src/chain.cpp. Includes a C++ wrapper
    and Boost tests for the genesis-only and post-IBD cases
    9582658aff
  7. pzafonte force-pushed on Mar 18, 2026
  8. pzafonte renamed this:
    kernel: add btck_chainstate_manager_get_locator
    kernel: add block locator to the C API
    on Mar 18, 2026
  9. pzafonte commented at 7:17 am on March 18, 2026: none
    Updated to address the feedback. Exposes btck_BlockLocator with btck_chainstate_manager_get_locator, btck_block_locator_to_bytes, and btck_block_locator_destroy
  10. stickies-v commented at 5:33 pm on March 18, 2026: contributor

    Concept NACK, I think this belongs in a p2p library. I would be interested in reviewing related changes such as btck_BlockTreeEntry* btck_block_tree_entry_get_ancestor(const btck_BlockTreeEntry* entry, int height) to efficiently skip multiple entries, or btck_BlockTreeEntry* btck_block_tree_entry_get_common_ancestor(const btck_BlockTreeEntry* a, const btck_BlockTreeEntry* b).

    and every external client using the kernel needs to implement them in order to use the network

    Right, but that’s true for a lot of p2p functionality. I don’t see why that means kernel should start exposing p2p?

    We do have a function that finds forks with block locators (FindForkInGlobalIndex) and I wonder if all clients implementing that might be a source of bugs

    I think btck_BlockTreeEntry* btck_block_tree_entry_get_common_ancestor(const btck_BlockTreeEntry* a, const btck_BlockTreeEntry* b) would address that concern? That function can then be called for every entry in the block locator/some array of block hashes? There’s a bit more calling overhead like that but I don’t think that’s going to be meaningful?

  11. sedited commented at 9:55 pm on March 18, 2026: contributor

    I think btck_BlockTreeEntry* btck_block_tree_entry_get_common_ancestor(const btck_BlockTreeEntry* a, const btck_BlockTreeEntry* b) would address that concern?

    Initially I thought the immediate benefit of having a higher level method is that it already takes care of the required synchronization. We don’t have a mechanism to expose a stable view of the chain, or lock cs_main and for stuff like finding ancestors in the chain, that seemed relevant. Looking at it a bit more closely now, I’m not sure that is something actually desirable. A common ancestor function as you suggest it, does not necessarily require additional synchronization , the usual assumption that a looked up entry from the chain immediately turns stale still holds. If a block request formed by such a stale entry ends up putting us on a fork, we should just repeat the operation. The guarantee we want to provide is eventual consistency.

    This means I’d support your suggestion @stickies-v and would recommend closing this pull request for now. If exposing such a lower level function proves not good enough, this can always be revisited.

  12. yancyribbens commented at 10:18 pm on March 18, 2026: contributor

    Right, but that’s true for a lot of p2p functionality. I don’t see why that means kernel should start exposing p2p?

    I think this questions reveals the ambiguity of where responsibilities are for library code. As I understand it, block validation is dangerous for a p2p crate to recreate because it risks forking or partitioning the network if done incorrectly. However, a p2p crate that exports code to perform various network functions like ping, do not cause connected clients to get wrong information if it’s not implemented correctly (since the node would be booted soon). If the chain locator is implemented incorrectly, the node would stay network connected, but possibly relay false information to the network being on a stale tip? Therefore, this locator code seems somewhat more integral than your common p2p functionally as I understand it. That is to say, if implementation of the locator code is buggy, could it bomb some portion of the network?

    I’m not necessarily against having this be in a supported p2p crate, however it would be nice to have some assurance that locator code is functionally correct. For example, identify some common agreed upon behavior that the p2p crate must pass to correctly implement the locator. In other words, how can we make sure that various libs implement it exactly if it’s not to be exposed here (for now and in the future).

  13. pzafonte commented at 11:17 am on March 19, 2026: none
    Per the discussion, I will close out this PR and plan to add get_ancestor to the C API.
  14. stickies-v commented at 12:34 pm on March 19, 2026: contributor

    Therefore, this locator code seems somewhat more integral than your common p2p functionally as I understand it.

    I’m not sure if I understand you correctly, but I think you’re saying that because bugs in block locator logic could lead to forking or network partitioning, we should consider not letting p2p libraries handle this? If so, I strongly disagree. Kernel should be really good at validation, a p2p library should be really good at p2p.

    block validation is dangerous for a p2p crate to recreate

    I agree (and I don’t think block locators have anything to do with block validation)

  15. yancyribbens commented at 5:23 pm on March 19, 2026: contributor

    I’m not sure if I understand you correctly, but I think you’re saying that because bugs in block locator logic could lead to forking or network partitioning, we should consider not letting p2p libraries handle this?

    Yes, that is what I was getting at. My understanding is that critical consensus code was being provided via the C api to prevent other implementations from duplicating this functionality and making mistakes. There is also the issue of how to keep things fresh in that if block code is changed, and core updates the locator code, and there is a bunch of clones of locator code, how does one keep things in sync.

    Per the discussion, I will close out this PR and plan to add get_ancestor to the C API. @pzafonte Sorry to bump you around so much. Consider opening a PR for the locator stuff in p2p lib here https://github.com/rust-bitcoin/rust-bitcoin/tree/master/p2p.

  16. pzafonte closed this on Mar 20, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-03-20 18:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me