Skip to content

Feat/prover db 2 producer#187

Open
rishitesh-snt wants to merge 8 commits intomainfrom
feat/prover-db-2-producer
Open

Feat/prover db 2 producer#187
rishitesh-snt wants to merge 8 commits intomainfrom
feat/prover-db-2-producer

Conversation

@rishitesh-snt
Copy link
Copy Markdown
Contributor

@rishitesh-snt rishitesh-snt commented Apr 28, 2026

Rationale for this change

Introduces pallet-prover-db-indexer with the producer side: on_finalize reads frame_system::Events, extracts pallet_tables::{SchemaUpdated, TablesCreatedWithCommitments, TableDropped} and
pallet_indexing::QuorumReached into a BlockIndex, and persists it to offchain storage. Wires the pallet into the runtime at pallet_index(111); offchain_worker is a no-op stub until PR 3.

Adds the operator-facing wiring for the upcoming prover-db-indexer pallet:
a `--prover-db-url` CLI flag that, at startup, seeds the URL into the OCW
persistent local-storage key `prover_db_indexer::prover_db_url` before the
first block is authored. Also surfaces a clear error if `--prover-db-url`
is set without `--enable-offchain-indexing=true`, since the pallet's
on_finalize writes would otherwise be silently dropped.

The storage key is kept as a local literal in `node/src/service.rs` so
this change is independent of the pallet, which is added in a follow-up
PR. The literal must stay in sync with `pallet_prover_db_indexer::PROVER_DB_URL_KEY`
once that pallet lands; the next PR refactors the node to import it.

The flag is inert until the pallet ships, so this PR cannot affect the
running system.
@rishitesh-snt rishitesh-snt requested review from a team as code owners April 28, 2026 14:30
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

1.69.0

Bug Fixes

  • add basic documentation to runtime crate (30c26e7
  • add missing docs for runtime module items (52a2905
  • add missing docs to chain-utils (c8235c6
  • address warnings in on-chain-table (095a856
  • address warnings in pallet-rewards mock module (886bc36
  • allow deprecated CurrencyAdapter usage (cfe0517
  • allow missing docs in private items in test_end_row_limits binary (7700cd6
  • allow missing_docs_in_private_items on event forwarder contract (b2d6f8b
  • allow unused private_key variables in pallet-keystore benchmarks (c218f0d
  • declare anonymous lifetime in commitment-sql proptest helper (63b3fc0
  • declare anonymous lifetimes in canaries parse functions (f81e9de
  • document all items in watcher main module (2fe60db
  • document memory_commitment_map module in commitment-map (32a38e3
  • document missing items in canaries (72c5f33
  • document missing items in event-forwarder (5408075
  • document modules in chain-utils (3eb6545
  • document modules in rpc crate (19cf1af
  • don't hide elided lifetimes in backwards compatibility test case generator (4e6968e
  • don't import frame_benchmarking if runtime-benchmarks is disabled in node (32cfca3
  • expect AttestationInfo::block_number to be dead code in canaries (7753c44
  • expect some dead code in NewFullBase in node (fe06f5e
  • ignore unused error variable in watcher main module (d330fe5
  • ignore unused variable in attestation-tree test (ce8adf3
  • ignore unused variable in pallet-attestation benchmarks (b0ef4a7
  • implement benchmark configurations for runtime outside runtime api implementation (d1a3db8
  • only define migrations with runtime-benchmarks disabled (26e8804
  • pallet: silence clippy::manual_inspect from FRAME macro expansion (5ec8511
  • privatize deposit_event in pallet-rewards (6c1caaf
  • privatize deposit_event in pallet-smartcontracts (fe43a19
  • privatize deposit_event in pallet-system-tables (8bf7c21
  • privatize deposit_event in pallet-tables (da951a5
  • privatize pallet-keystore deposit_event (e878e37
  • privatize pallet-permissions deposit_event (099a7ba
  • privatize system-contracts deposit_event (305dfc9
  • privatize zkpay deposit_event (9d5993c
  • propagate tui error in update_ui in watcher (fe943eb
  • remove dead code in chain-utils (0070600
  • remove dead code in node (6958ec6
  • remove unused block_number parameter from verify_attestations in watcher (6225426
  • remove unused block_number parameter from verify_signature in watcher (08f3bff
  • remove unused const in pallet-tables test (e7bf9f5
  • remove unused const in runtime test (c7e0add
  • remove unused dependencies from sxt-core (361f8a0
  • remove unused destructure variables in verify_attestation in watcher (dc04d24
  • remove unused import in memory_commitment_map test (4c2300a
  • remove unused import in pallet-attestation benchmarks (5fa662e
  • remove unused import in pallet-commitments migrations (ecf6a05
  • remove unused imports and format imports in chain-utils (5cd269b
  • remove unused imports in attestation-tree (91f5d61
  • remove unused imports in node (1f4c7a8
  • remove unused imports in pallet-smartcontracts (b7fa723
  • remove unused imports in pallet-tables (a08ccfd
  • remove unused imports in runtime (614a1e3
  • remove unused imports in test_end_row_limits (0328143
  • remove unused imports in watcher (340d27b
  • remove unused substrate key path from watcher client (2bd4d02
  • switch hex to being a dev dependency in rpc crate (7b01208
  • warn unused_crate_dependencies in sxt-core (62c85b7

Features

  • allow SCI namespace creation without special permissions (092ba68
  • node: add --prover-db-url CLI flag and OCW seeding (4e1b6ee
  • pallet: add prover-db-indexer pallet (producer half) (525f694

- Hoist `PROVER_DB_URL_KEY` into `sxt-core` so node and the
  prover-db-indexer pallet share one canonical key (with `/` as the
  domain separator, matching substrate convention).
- Tighten the CLI doc since it surfaces in `--help`; drop the internals.
- Enable clap `env` feature so `PROVER_DB_URL` env var also configures it.
- Drop the eprintln! warning when offchain indexing is off without
  `--prover-db-url` — that's the typical case, not worth shouting.
- Pass `&Cli` into `new_full_base` instead of an owned URL, so future
  options can be threaded through without further signature changes.
- Hoist `use codec::Encode` to the file's import block.
@rishitesh-snt rishitesh-snt force-pushed the feat/prover-db-2-producer branch from 7f05b5b to 4d8b6cb Compare April 29, 2026 05:41
Standardize on "prover-db indexer URL" across `sxt_core`, the node CLI,
and the service-side seeding helper. Drop the pallet-internal references
(`on_finalize`, `sp_io::offchain_index::set`) from the runtime check —
that scaffolding lands in follow-up PRs and shouldn't leak into PR1.
@rishitesh-snt rishitesh-snt force-pushed the feat/prover-db-2-producer branch from 4d8b6cb to 1acbe12 Compare April 29, 2026 08:01
Per review: sxt-core groups items by the pallet they belong to (with the
exception of `IdentLength`/`ByteString`). Move `PROVER_DB_URL_KEY` out of
the top-level into a new `prover_db_indexer` module to follow that
pattern. The node now imports it as
`sxt_core::prover_db_indexer::PROVER_DB_URL_KEY`.
Introduces `pallet-prover-db-indexer`, an offchain worker that will
forward table lifecycle and `pallet_indexing` quorum events to an
external prover-db indexer over HTTP.

This PR ships only the **producer** side (`on_finalize`):

- Reads `frame_system::Events`, downcasts via `RuntimeEvent: TryInto<...>`
  (no SCALE re-encoding), extracts `pallet_tables::{SchemaUpdated,
  TablesCreatedWithCommitments, TableDropped}` and
  `pallet_indexing::QuorumReached` into a `BlockIndex` of `BlockEvent`s.
- Persists non-empty `BlockIndex`es to offchain storage keyed by block
  number using `sp_io::offchain_index::set` (a no-op unless the node
  was started with `--enable-offchain-indexing=true`).

The **consumer** half (HTTP forwarding via `offchain_worker`) lands in
the follow-up PR; until then `offchain_worker` is a no-op stub. Because
producer writes are gated by `--enable-offchain-indexing` at the node
level — and the operator-facing flag added in the previous PR refuses
to seed `--prover-db-url` without it — landing this PR alone cannot
affect a running system.

Wiring:
- Workspace member + workspace dep entry in root `Cargo.toml`.
- Runtime registers the pallet at `pallet_index(111)` with
  `Config<native_api::Api>`.
- `node/src/service.rs` switches its URL-key literal over to
  `sxt_runtime::pallet_prover_db_indexer::PROVER_DB_URL_KEY`, replacing
  the local placeholder introduced in the previous PR.
`#[pallet::hooks]` expands into code that uses `map_err` over `inspect_err`,
which `clippy --all-features` flags under `clippy::manual_inspect`. The
hit is in macro-generated code, not in our hook bodies, so allow it on
the pallet module's existing allow list.
@rishitesh-snt rishitesh-snt force-pushed the feat/prover-db-2-producer branch from 1acbe12 to 1a60cac Compare April 30, 2026 12:20

Watches for these events from other pallets and relays them:
- `pallet_tables::SchemaUpdated`
- `pallet_tables::TablesCreatedWithCommitments`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FYI I believe this one is irrelevant now, we don't really support creating a table w/ an initial commitment and snapshot url. The event and extrinsic are still there for backwards compatibility but almost nobody has permission to use them

Comment on lines +33 to +35
As of commit `dd873ed`, the node boots with a loud `warning:` to stderr
if this flag is not set; running with `--prover-db-url` *without* the flag
is a hard startup error.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This commit isn't in main since it was squashed, but also I think we removed this warning since most nodes will not be indexing to provers

Comment on lines +71 to +84
impl pallet_prover_db_indexer::Config for Runtime {
type RuntimeEvent = RuntimeEvent;

// Used to resolve pallet_indexing's pallet index dynamically via
// PalletInfoAccess::index(), so reordering construct_runtime! never
// breaks the filter silently.
type IndexingPallet = Indexing;

// Variant index of `QuorumReached` within pallet_indexing::Event.
// The runtime supplies a resolver that looks the variant up by name
// at startup via scale_info::TypeInfo. See
// `DynamicQuorumReachedIndex` in runtime/src/lib.rs.
type QuorumReachedVariantIndex = DynamicQuorumReachedIndex;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is outdated. but also, I think it's probably not worth including in this README? Anybody looking to implement this pallet in their runtime would learn how by just looking at the api reference for this trait

with `--features indexer` (see the sxtdb repo), then launch
`sxt-node` with `--prover-db-url http://<prb-service-host>:<port>`.
The harness at `spaceandtimefdn/sxt-int-harness` (standalone crate)
drives table/data actions against the node via a TOML file.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This section doesn't seem necessary to include in the readme, especially the unit tests, seems destined to become outdated.

--offchain-worker=always \
--enable-offchain-indexing=true \
--prover-db-url http://127.0.0.1:9999
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the docs of this pallet should be pretty agnostic of the CLI args. I think it would make sense to say, generally, that the complete functionality of this offchain worker requires enabling offchain indexing, offchain workers, and the prover db url storage to be set. And then maybe mention in the --prover-db-url help text that the other two CLI flags need to be enabled for complete functionality. The point being that this pallet's docs aren't making assumptions about the CLI defined by the node that uses this pallet.

Comment on lines +101 to +106
log::debug!(
target: "prover_db_indexer",
"on_finalize({}): writing {} events to offchain DB",
block_number,
index.events.len(),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but I believe logs within the runtime should be performed with sp_tracing macros, not log

this in `finalize_quorum`: it converts the indexer's Arrow IPC
submission to an `OnChainTable`, appends commitment meta columns,
and postcard-serializes the result. The prover-db-indexer never
decodes this payload — it's an opaque pass-through to the server.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NIT: I'm not super against this being mentioned here, but it does feel like it would be more appropriate as documentation of the Prover db api, not of this pallet.

Arrow schema lacks a `META_ROW_NUMBER BIGINT NOT NULL` column. If your
on-chain table DDLs don't include this column, the first forward
attempt will fail at the server. Either add the column to the DDL or
patch the forwarder's `DEDUP_KEY_COLUMN` constant.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This doesn't really seem relevant to this pallet. It's relevant to the tables/indexing pallets that generate the META_ROW_NUMBER, and the PRB api that handles it in this special way, but I don't think this pallet does or will do anything with it

// indexing quorum yields one, anything else yields nothing).
// The extractors are pure: they take an event and return what
// would be appended, leaving accumulation to the caller.
let events = polkadot_sdk::frame_system::Pallet::<T>::read_events_no_consensus()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we go with this approach, I think we should use read_events_for_pallet instead. This one reads all system events so it has serious weight implications, I think

// ─── PRODUCER ───────────────────────────────────────────────────
// Runs during block execution (including sync). Captures events
// and persists them to the offchain DB for the OCW to consume.
fn on_finalize(n: BlockNumberFor<T>) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry I didn't realize this sooner, but I don't think we can use this hook for indexing. Any code that runs synchronously in the runtime needs to be benchmarked and "weights calculated" so that the chain can make sure not to schedule too much work into one block. So, the docs for the Hooks trait say that the weight for on_finalize needs to be accounted for and returned by on_initialize.

However, I don't think we can know the weight. The weight would depend greatly on the number of inserts and table creations in the block, which we have no way of knowing on_initialize. We may be able to know this about the previous block, and just use on_initialize to index all events from the previous block, but I'm not 100% sure about that.

This leans me back towards thinking we need to be collecting these events into some intermediate storage during the relevant extrinsics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants