Skip to content

Ledger topology index for topological bootstrap#5069

Open
pwojcikdev wants to merge 7 commits into
nanocurrency:developfrom
pwojcikdev:topo-index-3
Open

Ledger topology index for topological bootstrap#5069
pwojcikdev wants to merge 7 commits into
nanocurrency:developfrom
pwojcikdev:topo-index-3

Conversation

@pwojcikdev
Copy link
Copy Markdown
Contributor

@pwojcikdev pwojcikdev commented May 4, 2026

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 new topo_index_enabled ledger 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_height is defined as 1 + max(topo_height of dependencies), with a floor of 1 for genesis and rootless blocks (e.g. an epoch_open on 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

  • New topology table indexed by (topo_height, hash) with big-endian key encoding so byte-order iteration matches numeric order.
  • New topo_height field on block_sideband. Computed during ledger processing and maintained on rollback.
  • topo_index_enabled flag 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.
  • New ledger::populate_topo_index() migration: walks every block via bounded DFS, computes topo_height into 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.
  • New ledger::drop_topo_index(): clears the topology table and disables the flag. Backs the --drop_topo_index CLI command and is required before enabling pruning on a ledger that already has the topology index populated.
  • Genesis seeding moved into ledger::seed_genesis() so a fresh ledger can be initialized with the topology index off. Driven by a new ledger_options struct passed at construction; the persisted meta flag still wins for existing ledgers, so the option only affects first-init.
  • The backfill migration release-asserts on missing dependencies — pruned ledgers are not supported by populate_topo_index, and the node refuses to start with both pruning and the topology index enabled.
  • Ledger version storage moved from a standalone view into the meta view. No change to on-disk layout (same key, same value).

CLI changes

New one-off commands on nano_node:

Command Description
--populate_topo_index Walks the ledger, computes and persists topo_height for every block, populates the topology table, and enables the topo_index_enabled flag. Reports "Topology index is already populated" if the flag is already set. May take a long time on large ledgers.
--drop_topo_index Clears the topology table and disables the topo_index_enabled flag. 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:

Flag Description
--disable_topo_index Initialize a fresh ledger without the topology index. Intended for pruning nodes (which must have the index off). Has no effect on an existing ledger — the persisted meta flag wins on re-open; to disable on an existing ledger use --drop_topo_index.

Pruning compatibility

The topology index is incompatible with pruning. Concretely:

  • A fresh ledger started with --enable_pruning or --disable_topo_index comes up with the topology index disabled.
  • A node started with --enable_pruning against a ledger that already has the topology index populated refuses to start. Run --drop_topo_index first, then re-enable pruning.

JSON response changes

topo_height is added to block details in three RPC handlers, alongside the existing height field. Always emitted, formatted as a decimal string.

RPC Where it appears
block_info / block Top-level field
blocks_info Per-block entry under blocks
account_history Per-entry field under history

Value semantics:

  • 0 for blocks on a ledger that was upgraded from v25 and where --populate_topo_index has not been run, and for blocks on ledgers initialized with the topology index disabled (pruning / --disable_topo_index).
  • Non-zero for all blocks once the topology index is enabled.

@pwojcikdev pwojcikdev changed the title Block topology index for topological bootstrap Ledger topology index for topological bootstrap May 4, 2026
@gr0vity-dev-bot
Copy link
Copy Markdown

gr0vity-dev-bot commented May 5, 2026

Test Results for Commit 4f2b598

Pull Request 5069: Results
Overall Status:

Test Case Results

  • 5n4pr_conf_10k_bintree: PASS (Duration: 110s)
  • 5n4pr_conf_10k_change: PASS (Duration: 126s)
  • 5n4pr_conf_change_dependant: PASS (Duration: 111s)
  • 5n4pr_conf_change_independant: PASS (Duration: 105s)
  • 5n4pr_conf_send_dependant: PASS (Duration: 105s)
  • 5n4pr_conf_send_independant: PASS (Duration: 110s)
  • 5n4pr_rocks_10k_bintree: PASS (Duration: 106s)
  • 5n4pr_rocks_10k_change: PASS (Duration: 224s)

Last updated: 2026-05-10 14:40:33 UTC

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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_height to block_sideband, compute/maintain it during block processing, and delete corresponding topology rows on rollback/pruning.
  • Add topology store view + table, plus a two-phase ledger::populate_topo_index() migration to backfill existing ledgers and flip topo_index_enabled.
  • Expose topo_height via RPC responses and add --populate_topo_index CLI 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.hpp no longer declares nano::store::ledger::version_view (it only includes meta.hpp). This makes the header non-self-contained and can break compilation if a TU includes version.hpp expecting the historical version_view symbol without also including store/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.

Comment thread nano/store/tables.hpp
Comment thread nano/secure/ledger_processor.cpp
Comment thread nano/secure/ledger_processor.cpp
@pwojcikdev pwojcikdev added database structure If the database changes it needs updating in the nanodb repository cli Changes related to the Command Line Interface rpc Changes related to Remote Procedure Calls labels May 5, 2026
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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 44 out of 44 changed files in this pull request and generated 4 comments.

Comment thread nano/core_test/block_store.cpp
Comment thread nano/secure/ledger_topo_index.cpp Outdated
Comment thread nano/node/cli.cpp
Comment thread nano/node/cli.cpp Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 44 out of 44 changed files in this pull request and generated 11 comments.

Comment thread nano/secure/ledger.cpp
Comment thread nano/node/json_handler.cpp
Comment thread nano/node/json_handler.cpp
Comment thread nano/node/json_handler.cpp
Comment thread nano/secure/ledger.cpp
Comment thread nano/secure/ledger_rollback.cpp
Comment thread nano/secure/ledger_rollback.cpp
Comment thread nano/secure/ledger_rollback.cpp
Comment thread nano/secure/ledger_rollback.cpp
Comment thread nano/core_test/ledger.cpp Outdated
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli Changes related to the Command Line Interface database structure If the database changes it needs updating in the nanodb repository rpc Changes related to Remote Procedure Calls

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants