Skip to content

feat: add native indexer mode - #2051

Draft
skylar-simoncelli wants to merge 30 commits into
mainfrom
skylar-embedded-indexer
Draft

feat: add native indexer mode#2051
skylar-simoncelli wants to merge 30 commits into
mainfrom
skylar-embedded-indexer

Conversation

@skylar-simoncelli

@skylar-simoncelli skylar-simoncelli commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an optional --indexer node mode that starts and supervises the native indexer worker
  • port the complete indexer source tree directly into midnight-node, with no submodule and no separately released or deployed indexer component
  • ship the worker in the same midnight-node image and preserve the existing GraphQL API, SQL schema, configuration, metrics, and indexer behavior
  • keep the worker on its proven independent Cargo dependency graph so the node consensus dependency graph remains unchanged
  • keep indexer failure non-fatal to the node and restart the worker after unexpected exits
  • make --indexer imply archive retention for both historical state and block bodies
  • fix the in-memory pub-sub panicking on the first indexed c2m-bridge event (bug also present upstream)
  • speed up chain indexing 4.4x (8.3 -> 36.8 blocks/s measured on devnet): prefetch blocks concurrently with indexing, fetch several catch-up blocks at once (fetch_concurrency), fetch system parameters with the block instead of per-block on the sequential path, and make gc cadence configurable (gc_block_interval)
  • add per-phase Prometheus histograms to the chain indexer so replay cost is attributable in production

Architecture

The externally visible primitive is midnight-node --indexer: one node image, one deployment, and one node-managed lifecycle. Internally, the node supervises a sibling midnight-indexer worker built from the source now owned by this repository.

The worker is compiled separately with indexer/Cargo.toml and its checked-in lockfile. This is intentional: the original Ledger 8 indexer depends on older Base Crypto, Serialize, Storage, and transient-crypto revisions. Linking those crates into the Ledger 9 node process allows root Cargo patches to rewrite the historical verifier graph. The process boundary preserves the exact dependency closure used by the current standalone indexer without changing node consensus dependencies.

This is source and release consolidation, not an external runtime dependency. The standalone midnight-indexer repository and deployment can be retired once parity, replay, and performance validation are complete.

The indexer performs historical runtime-state queries in addition to reading block bodies. --indexer therefore forces both state and block archive modes. An existing database created with pruned state must be rebuilt because pruned historical trie state cannot be recovered in place.

Performance

Measured on devnet (683k blocks) against a fully synced colocated archive node, 4/8 CPU 10/14 GiB pod, one variable changed per deployment:

Configuration Chain indexing rate Full devnet replay
Ported indexer, unmodified 8.3 blocks/s ~23 h
+ concurrent fetch/process pipelining 9.8 blocks/s ~19 h
+ fetch_concurrency 8 12.2 blocks/s ~16 h
+ system parameters fetched with the block 36.8 blocks/s ~5.2 h
+ gc_block_interval 16 71.9 blocks/s ~2.6 h
+ fetch_concurrency 32 111.2 blocks/s 1 h 42 m measured end to end

A fresh from-genesis replay of the full devnet chain (685,016 blocks) on the final build completed in 1 h 42 m with zero worker exits, indexing the chain's c2m-bridge event and re-detecting the D-parameter change at exactly the same block as the dedicated indexer. Remaining per-block cost at 111 blocks/s is dominated by the ledger SQLite FULL-fsync persist (5.7 ms). Steady-state GraphQL block queries measure p50 1.50 ms / p99 2.09 ms against the embedded service versus p50 3.45 ms / p99 4.70 ms against the dedicated internal service from the same in-cluster client. ledger-db.sqlite reaches ~32 GB for devnet; disk sizing must budget for it. The SPO indexer's historical epoch catch-up is separately ~148x faster after rewriting a Cardano db-sync query whose generic plan scanned 1.6M rows to return one.

Validation

Devnet validation completed so far:

  • node runs at devnet chain head with the ported indexer replaying the full history; zero worker or container restarts across sustained multi-hour segments after the archive-pruning and bridge-event fixes
  • byte-exact GraphQL parity with the deployed dedicated devnet indexer at multiple heights for blocks (including author), and for the systemParameters projection including the D-parameter change history
  • systemParameters_getAriadneParameters responses match validator-01 byte-for-byte at multiple epochs
  • per-phase histograms (indexer_*_duration_seconds) expose fetch/convert/ledger/persist/system-parameters/storage/publish timings

Remaining validation

  • fresh full replay from genesis on the final image: 685,016 blocks in 1 h 42 m, zero worker exits, byte-exact parity spot checks across six heights, transactions, authors, and system-parameters history
  • steady-state GraphQL latency comparison against the dedicated deployment
  • loaded/concurrent GraphQL benchmark and subscription behavior under load
  • Wallet SDK correctness, initial-sync, and client-side performance comparison
  • resolve DCO for the pre-existing unsigned branch commit

Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
@skylar-simoncelli skylar-simoncelli added skip-changes-check-jira bot:ai-assisted Authored or substantially edited by an AI agent labels Aug 19, 2026
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
@datadog-official

This comment has been minimized.

Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
@skylar-simoncelli
skylar-simoncelli marked this pull request as ready for review August 19, 2026 18:35
@skylar-simoncelli
skylar-simoncelli requested a review from a team as a code owner August 19, 2026 18:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 918c258eac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread node/src/indexer.rs Outdated
telemetry_config: telemetry::Config { tracing_config, metrics_config },
} = Config::load().context("load indexer configuration")?;

log::info!(application_config:?, infra_config:?; "starting embedded indexer");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Redact the Blockfrost credential from startup logs

Whenever --indexer is enabled, this info-level log formats the entire InfraConfig; its derived Debug output includes SpoNodeConfig.blockfrost_id, which is stored as a plain String until it is converted to SecretString later. This exposes the Blockfrost API credential to routine production logs, so log only non-sensitive fields or redact the credential before formatting the configuration.

Useful? React with 👍 / 👎.

Comment thread changes/added/embedded-indexer.md Outdated
@@ -0,0 +1,10 @@
#indexer #api

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move the change file into the node component

This node feature's change file is outside changes/node/added/, even though the release workflow packages and filters component notes under changes/node (.github/workflows/release-image.yml lines 473-476) and the archive workflow likewise processes only that directory. Consequently this feature will be omitted from the node release changelog; move the file into the node component directory.

AGENTS.md reference: AGENTS.md:L195-L201

Useful? React with 👍 / 👎.

Comment thread node/src/command.rs Outdated
Comment on lines +348 to +349
async move {
if let Err(error) = crate::indexer::run() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make the embedded runner cancellable during node shutdown

When shutdown is initiated by SIGINT or by another essential node task failing, rather than by SIGTERM, this synchronous run() call remains inside a single poll of the TaskManager's blocking future and cannot observe the TaskManager exit signal; the nested indexer runtime itself only installs SIGTERM handlers. The Substrate runner therefore waits its full 60-second runtime shutdown timeout before leaking the blocked task, making Ctrl-C and internal-failure shutdowns stall; propagate node cancellation into the nested runtime or otherwise ensure this call can return for every node shutdown path.

Useful? React with 👍 / 👎.

@skylar-simoncelli
skylar-simoncelli marked this pull request as draft August 19, 2026 21:26
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
@skylar-simoncelli skylar-simoncelli changed the title feat: embed indexer in dedicated node mode feat: add native indexer mode Aug 20, 2026

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Opengrep OSS found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

zizmor found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Comment thread indexer/qa/tests/data/static/qanet/cardano-stake-addresses.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/cardano-stake-addresses.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/cardano-stake-addresses.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/cardano-stake-addresses.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/cardano-stake-addresses.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/token-holding-contracts.jsonc Fixed
Comment thread indexer/qa/tests/data/static/qanet/token-holding-contracts.jsonc Fixed
Comment on lines +1 to +33
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p chain-indexer --locked --features cloud --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/chain-indexer" /runtime/usr/local/bin && \
mv /build/chain-indexer/bin/entrypoint.sh /runtime/usr/local/bin && \
mkdir -p /runtime/opt/chain-indexer && \
mv /build/chain-indexer/config.yaml /runtime/opt/chain-indexer

FROM debian:trixie-slim@sha256:f6e2cfac5cf956ea044b4bd75e6397b4372ad88fe00908045e9a0d21712ae3ba AS runtime
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates=20250419 && \
rm -rf /var/lib/apt/lists/*
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/chain-indexer && \
chown appuser:appuser /var/run/chain-indexer
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/chain-indexer
ENTRYPOINT ["entrypoint.sh"]
Comment on lines +1 to +31
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p indexer-api --locked --features cloud --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/indexer-api" /runtime/usr/local/bin && \
mv /build/indexer-api/bin/entrypoint.sh /runtime/usr/local/bin && \
mkdir -p /runtime/opt/indexer-api && \
mv /build/indexer-api/config.yaml /runtime/opt/indexer-api

FROM debian:trixie-slim@sha256:f6e2cfac5cf956ea044b4bd75e6397b4372ad88fe00908045e9a0d21712ae3ba AS runtime
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/indexer-api && \
chown appuser:appuser /var/run/indexer-api
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/indexer-api
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 8088
Comment on lines +1 to +36
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p indexer-standalone --locked --features standalone --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/indexer-standalone" /runtime/usr/local/bin && \
mv /build/indexer-standalone/bin/entrypoint.sh /runtime/usr/local/bin && \
mkdir -p /runtime/opt/indexer-standalone && \
mv /build/indexer-standalone/config.yaml /runtime/opt/indexer-standalone

FROM debian:trixie-slim@sha256:f6e2cfac5cf956ea044b4bd75e6397b4372ad88fe00908045e9a0d21712ae3ba AS runtime
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates=20250419 && \
rm -rf /var/lib/apt/lists/*
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/indexer-standalone && \
chown appuser:appuser /var/run/indexer-standalone && \
mkdir /data && \
chown appuser:appuser /data
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/indexer-standalone
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 8088
Comment on lines +1 to +27
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p indexer-tests --locked --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/indexer-tests" /runtime/usr/local/bin

FROM debian:trixie-slim@sha256:66b37a5078a77098bfc80175fb5eb881a3196809242fd295b25502854e12cbec AS runtime
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/indexer-tests && \
chown appuser:appuser /var/run/indexer-tests
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/indexer-tests
ENTRYPOINT ["indexer-tests"]
Comment on lines +1 to +33
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p spo-indexer --locked --features cloud --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/spo-indexer" /runtime/usr/local/bin && \
mv /build/spo-indexer/bin/entrypoint.sh /runtime/usr/local/bin && \
mkdir -p /runtime/opt/spo-indexer && \
mv /build/spo-indexer/config.yaml /runtime/opt/spo-indexer

FROM debian:trixie-slim@sha256:f6e2cfac5cf956ea044b4bd75e6397b4372ad88fe00908045e9a0d21712ae3ba AS runtime
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates=20250419 && \
rm -rf /var/lib/apt/lists/*
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/spo-indexer && \
chown appuser:appuser /var/run/spo-indexer
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/spo-indexer
ENTRYPOINT ["entrypoint.sh"]
Comment on lines +1 to +30
ARG RUST_VERSION
FROM lukemathwalker/cargo-chef:0.1.77-rust-$RUST_VERSION-trixie AS chef
WORKDIR /build

FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
SHELL ["/bin/bash", "-c"]
ARG PROFILE=release
COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --profile $PROFILE --recipe-path recipe.json
COPY . .
RUN cargo build -p wallet-indexer --locked --features cloud --profile $PROFILE && \
mkdir -p /runtime/usr/local/bin && \
mv "./target/${PROFILE/dev/debug}/wallet-indexer" /runtime/usr/local/bin && \
mv /build/wallet-indexer/bin/entrypoint.sh /runtime/usr/local/bin && \
mkdir -p /runtime/opt/wallet-indexer && \
mv /build/wallet-indexer/config.yaml /runtime/opt/wallet-indexer

FROM debian:trixie-slim@sha256:f6e2cfac5cf956ea044b4bd75e6397b4372ad88fe00908045e9a0d21712ae3ba AS runtime
RUN useradd -u 10001 -d /nonexistent -s /usr/sbin/nologin -M -c "" appuser && \
passwd -l appuser && \
mkdir /var/run/wallet-indexer && \
chown appuser:appuser /var/run/wallet-indexer
COPY --from=builder --chown=appuser:appuser /runtime /
USER appuser
WORKDIR /opt/wallet-indexer
ENTRYPOINT ["entrypoint.sh"]
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

gitleaks found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Checkov found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Comment thread indexer/README.md Fixed
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/indexer-tests/src/e2e.rs Fixed
Comment thread indexer/qa/tools/block-scanner/src/test-data-handler.ts Fixed
Comment thread indexer/qa/tools/block-scanner/src/test-data-handler.ts Fixed
Comment thread indexer/qa/tools/block-scanner/src/test-data-handler.ts Fixed
Comment thread indexer/qa/tools/block-scanner/src/test-data-handler.ts Fixed
Comment thread indexer/qa/tools/block-scanner/src/test-data-handler.ts Fixed
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/docker-compose.yaml Fixed
Comment thread indexer/indexer-tests/src/e2e.rs Fixed
Comment thread indexer/qa/scripts/test-hardfork-8to9.sh Fixed
Comment thread indexer/qa/scripts/test-runtime-upgrade.sh Fixed
Comment thread indexer/qa/tools/block-scanner/src/env.ts Fixed
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Comment thread indexer/qa/tests/README.md Fixed
Comment thread indexer/qa/tests/coverage/src/git.ts Fixed
Comment thread indexer/qa/tests/utils/toolkit/toolkit-wrapper.ts Fixed
Comment thread indexer/qa/tests/utils/toolkit/toolkit-wrapper.ts Fixed
Comment thread indexer/qa/tests/coverage/src/static-evidence.ts Fixed
Comment thread indexer/qa/tests/coverage/src/check.ts Fixed
Comment thread indexer/qa/tests/coverage/src/check.ts Fixed
Comment thread indexer/qa/tests/coverage/src/check.ts Fixed
Comment thread indexer/qa/tests/coverage/src/check.ts Fixed
Comment thread indexer/qa/tests/bunfig.toml Fixed
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
@skylar-simoncelli
skylar-simoncelli force-pushed the skylar-embedded-indexer branch 2 times, most recently from 2f204ed to f71324a Compare August 20, 2026 18:26
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
The ported schema-v4.graphql lost its tab-indented blank lines and
trailing newline, so the byte-exact schema check in the indexer test
recipe failed. Restore the file to the generator's exact output.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
The in-memory pub-sub had no channel for BridgeEventIndexed, so the
standalone and native flavors panicked the chain-indexer task on the
first indexed c2m-bridge event. The block was already saved, so the
worker resumed past it on restart, but every bridge event cost a
worker restart and subscription clients silently missed the event.

Add the missing broadcast channel with publisher/subscriber arms and
a drain task, plus a publish/subscribe regression test.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Phase timing on devnet attributed roughly half of the 125 ms per-block
cycle to awaiting the next block from the node stream. The existing
`.map(ready).buffered(blocks_buffer)` adapter cannot fetch ahead:
stream combinators only run while the consumer polls them, so fetching
and indexing were strictly serial.

Run the block stream on its own task feeding a bounded channel sized
by `blocks_buffer`, so block fetching overlaps block processing while
preserving ordering and the existing gap/duplicate handling.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Fetching one block takes about 11 sequential RPC awaits. During
by-height catch-up these are independent across heights except for the
authority cache, which is only needed to resolve block authors and is
invalidated by NewSession events.

Split make_block into make_raw_block, which fetches and assembles
everything except the author and can run for several heights at once,
and finish_block, which resolves the author against the sequential
authority cache in block order. The catch-up path now drives
make_raw_block through a bounded buffered stream (new node config
fetch_concurrency, default 8) while author resolution and parent-hash
verification stay sequential, so results are byte-identical to the
serial implementation.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Phase timing on devnet showed determine_system_parameters_change
spending 48 ms per block: a redundant at-block client construction plus
two runtime-API calls on the sequential indexing path, every block.

Fetch the D-parameter and terms and conditions in make_raw_block
instead, where the at-block client already exists and the lookups ride
the concurrent block prefetch, and carry the values on the node block.
Change detection compares the same values fetched at the same block
state, so detected changes and their recorded blocks are identical.
The Node trait loses fetch_system_parameters, which had no other
callers.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
The system-parameters change removed the node parameter from
index_block, but the genesis branch still fetches the genesis ledger
state from the node. Restore the parameter.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
The per-block gc pass consistently consumes its full time budget while
culling almost nothing during catch-up (2.6 nodes per 12 ms pass
measured on devnet), costing about 11% of replay wall time. Add
gc_block_interval (default 1, i.e. unchanged behavior) so deployments
can amortize the pass over several blocks with the same per-pass
budget.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Skylar Simoncelli <skylar@skylar.email>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:ai-assisted Authored or substantially edited by an AI agent skip-changes-check-jira

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants