Ledger topology index for topological bootstrap#5069
Open
pwojcikdev wants to merge 7 commits into
Open
Conversation
Test Results for Commit 4f2b598Pull Request 5069: Results Test Case Results
Last updated: 2026-05-10 14:40:33 UTC |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a topology index for the ledger: a per-block topo_height (topological order over the block dependency graph) plus a new topology table keyed by (topo_height, block_hash) to enable efficient dependency-respecting iteration (preparatory work for topological bootstrap). The index is gated by a persisted topo_index_enabled flag and can be backfilled via a new CLI command.
Changes:
- Add
topo_heighttoblock_sideband, compute/maintain it during block processing, and delete corresponding topology rows on rollback/pruning. - Add
topologystore view + table, plus a two-phaseledger::populate_topo_index()migration to backfill existing ledgers and fliptopo_index_enabled. - Expose
topo_heightvia RPC responses and add--populate_topo_indexCLI command; refactor ledger store version storage into the meta view.
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| nano/store/tables.hpp | Adds table::topology enum entry and documents intended purpose. |
| nano/store/rocksdb/backend_rocksdb.cpp | Treats topology table counts as iteration-based (exact but potentially slow). |
| nano/store/meta.hpp | Introduces meta_key and extends meta_view to store flags. |
| nano/store/meta.cpp | Implements generic meta get/put plus boolean flag helpers. |
| nano/store/ledger/version.hpp | Refactors version view header to rely on meta view. |
| nano/store/ledger/version.cpp | Removes legacy version_view implementation (now handled by meta_view). |
| nano/store/ledger/topology.hpp | Adds topology store view API and typed iterators. |
| nano/store/ledger/topology.cpp | Implements topology table CRUD/iteration helpers. |
| nano/store/ledger_upgrades.cpp | Updates version writes to put_version() and v25→v26 sideband rewrite. |
| nano/store/ledger_store.hpp | Wires topology view into ledger_store. |
| nano/store/ledger_store.cpp | Adds topology schema entry and initializes genesis topo row + enables topo flag for fresh DBs. |
| nano/store/fwd.hpp | Adds fwd decls and aliases ledger::version_view to store::meta_view. |
| nano/store/db_val.hpp | Adds topo_key support in db_val interface. |
| nano/store/db_val_templ.hpp | Implements db_val serialize/deserialize for topo_key. |
| nano/store/CMakeLists.txt | Adds topology sources; removes version.cpp from build. |
| nano/secure/network_params.cpp | Initializes genesis sideband topo_height=1. |
| nano/secure/ledger.hpp | Adds ledger_flags and declares populate_topo_index(). |
| nano/secure/ledger.cpp | Loads topo_index_enabled into ledger.flags at startup; removes topology entries during pruning. |
| nano/secure/ledger_topo_index.cpp | Implements two-phase topo backfill + verification + topology table population + flag flip. |
| nano/secure/ledger_rollback.cpp | Deletes topology entries when rolling back blocks. |
| nano/secure/ledger_processor.hpp | Declares helper to compute topo height from dependencies. |
| nano/secure/ledger_processor.cpp | Computes/records topo_height during processing; inserts into topology table when non-zero. |
| nano/secure/common.hpp | Adds nano::topo_key type. |
| nano/secure/common.cpp | Implements topo_key big-endian serialization for ordered iteration. |
| nano/secure/CMakeLists.txt | Adds ledger_topo_index.cpp to build. |
| nano/rpc_test/rpc.cpp | Updates store version access to get_version(). |
| nano/node/node.hpp | Changes store_version() return type to uint64_t and makes it const. |
| nano/node/node.cpp | Uses store.version.get_version() in node::store_version(). |
| nano/node/json_handler.cpp | Adds topo_height to several RPC responses. |
| nano/node/cli.cpp | Adds --populate_topo_index command to backfill and enable the index. |
| nano/lib/block_sideband.hpp | Adds topo_height member + ctor args (default 0). |
| nano/lib/block_sideband.cpp | Serializes/deserializes topo_height and includes it in sideband size. |
| nano/core_test/ledger.cpp | Adds extensive tests for flag persistence, processing invariants, rollback, and migration. |
| nano/core_test/ledger_upgrades.cpp | Updates version accessors to get_version(). |
| nano/core_test/block_store.cpp | Adds topo_key + topology_view tests and meta flag tests. |
Comments suppressed due to low confidence (1)
nano/store/ledger/version.hpp:4
nano/store/ledger/version.hppno longer declaresnano::store::ledger::version_view(it only includesmeta.hpp). This makes the header non-self-contained and can break compilation if a TU includesversion.hppexpecting the historicalversion_viewsymbol without also includingstore/fwd.hpp. Consider restoring the alias in this header (e.g.namespace nano::store::ledger { using version_view = nano::store::meta_view; }) or including the header that provides it, so the public API remains stable regardless of include order.
#pragma once
#include <nano/store/meta.hpp>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace the standalone ledger version view with meta_view-backed helpers for version reads and writes.
Introduce topo_key with big-endian serialization so lexicographic database iteration preserves topological height ordering.
Add a topology table and typed store view for storing block hashes by topological height with ordered iteration, seeking, latest lookup, count, clear, and existence checks. Initialize the genesis topology entry and persist a topo_index_enabled ledger flag. Load that flag once during ledger construction and cover the store view, key ordering, and flag caching behavior with tests.
Compute topo_height from block dependencies, seed genesis sidebands at height 1, and skip topology writes when the index flag is disabled. Remove topology entries during rollback and pruning, with ledger tests covering chain heights, state blocks, cleanup, and disabled indexing.
Compute topology heights with bounded DFS, verify dependency ordering, populate the topology table, and enable the topology index flag only after the migration completes.
Include sideband topo_height in block_info, blocks_info, and account_history RPC results.
Add ledger options and move genesis seeding into the ledger layer so new pruning ledgers can be initialized without creating the topology index.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a per-block
topo_height(a topological order over the ledger graph) and a new topology table that indexes blocks by this height. The index is opt-in for existing ledgers, gated by a newtopo_index_enabledledger flag, and can be backfilled or dropped via new CLI commands.Why
This is preparatory work for topological bootstrap. In a topological bootstrap the serving peer streams blocks to a bootstrapping node in dependency-respecting order, so the receiver can apply each block immediately on arrival without buffering, retrying, or chasing missing dependencies. The serving peer needs to walk its own ledger in topological order, and the topology index gives it that walk in O(1) per block.
topo_heightis defined as1 + max(topo_height of dependencies), with a floor of1for genesis and rootless blocks (e.g. anepoch_openon an unopened account). Because a block's height is strictly greater than any of its dependencies, iterating the topology table in ascending order yields blocks in a valid dependency order.What's in this PR
topologytable indexed by(topo_height, hash)with big-endian key encoding so byte-order iteration matches numeric order.topo_heightfield onblock_sideband. Computed during ledger processing and maintained on rollback.topo_index_enabledflag stored in the meta table. Fresh ledgers come up with the flag set by default; ledgers upgraded from v25, or fresh ledgers initialized with pruning or--disable_topo_index, come up with it cleared.ledger::populate_topo_index()migration: walks every block via bounded DFS, computestopo_heightinto the sideband (phase 1), then sequentially populates the topology table (phase 2). Two phases are kept separate because random index inserts interleaved with the DFS pass would be very slow. The flag is flipped only after both phases commit, so a partial migration never appears enabled.ledger::drop_topo_index(): clears the topology table and disables the flag. Backs the--drop_topo_indexCLI command and is required before enabling pruning on a ledger that already has the topology index populated.ledger::seed_genesis()so a fresh ledger can be initialized with the topology index off. Driven by a newledger_optionsstruct passed at construction; the persisted meta flag still wins for existing ledgers, so the option only affects first-init.populate_topo_index, and the node refuses to start with both pruning and the topology index enabled.CLI changes
New one-off commands on
nano_node:--populate_topo_indextopo_heightfor every block, populates the topology table, and enables thetopo_index_enabledflag. Reports "Topology index is already populated" if the flag is already set. May take a long time on large ledgers.--drop_topo_indextopo_index_enabledflag. Required before enabling pruning on a ledger that has the topology index populated. Reports "Topology index is not enabled" if the flag is already cleared.New launch flag on
nano_node:--disable_topo_index--drop_topo_index.Pruning compatibility
The topology index is incompatible with pruning. Concretely:
--enable_pruningor--disable_topo_indexcomes up with the topology index disabled.--enable_pruningagainst a ledger that already has the topology index populated refuses to start. Run--drop_topo_indexfirst, then re-enable pruning.JSON response changes
topo_heightis added to block details in three RPC handlers, alongside the existingheightfield. Always emitted, formatted as a decimal string.block_info/blockblocks_infoblocksaccount_historyhistoryValue semantics:
0for blocks on a ledger that was upgraded from v25 and where--populate_topo_indexhas not been run, and for blocks on ledgers initialized with the topology index disabled (pruning /--disable_topo_index).