Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pallets/prover_db_indexer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ events forward via HTTP+protobuf:
- `pallet_tables::TableDropped` → `drop_table`
- `pallet_indexing::QuorumReached` → `put_batches`

The consumer is configured via node-supplied config keys — see
Gated by `prover_db_indexer/enabled` (default `false`). Once enabled,
the consumer is configured via node-supplied config keys — see
[`sxt_core::prover_db_indexer::ProverDbConsumerConfig`] for the
indexer URL, include filters, block-per-invocation cap, and OCW
lock deadline.
3 changes: 3 additions & 0 deletions pallets/prover_db_indexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ pub mod pallet {
EventRecord<T>: TryInto<DBEvent<T>>,
{
fn run_consumer() -> Result<(), ConsumerError> {
if !ProverDbConsumerConfig::enabled(native::config::config::get) {
return Ok(());
}
let config = ProverDbConsumerConfig::try_from_map(native::config::config::get)?;
// Serialize concurrent OCW invocations. Substrate spawns
// `offchain_worker` for every imported block, and rounds can
Expand Down
23 changes: 22 additions & 1 deletion pallets/prover_db_indexer/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ use polkadot_sdk::sp_runtime::offchain::Duration;
use proof_of_sql_commitment_map::CommitmentSchemeFlags;
use prost::Message;
use sxt_core::indexing::{BatchId, DataQuorum, SubmitterList};
use sxt_core::prover_db_indexer::{PROVER_DB_CONFIG_INCLUDE_KEY, PROVER_DB_CONFIG_URL_KEY};
use sxt_core::prover_db_indexer::{
PROVER_DB_CONFIG_ENABLED_KEY,
PROVER_DB_CONFIG_INCLUDE_KEY,
PROVER_DB_CONFIG_URL_KEY,
};
use sxt_core::tables::{QuorumScope, Source, TableIdentifier, TableType};

use crate::mock::*;
Expand Down Expand Up @@ -78,6 +82,7 @@ fn setup_with_config(
}
});
let mut config_store = std::collections::HashMap::new();
config_store.insert(PROVER_DB_CONFIG_ENABLED_KEY.to_string(), "true".to_string());
config_store.insert(PROVER_DB_CONFIG_URL_KEY.to_string(), MOCK_URL.to_string());
config_store.insert(
PROVER_DB_CONFIG_INCLUDE_KEY.to_string(),
Expand Down Expand Up @@ -145,6 +150,22 @@ fn ocw_skips_when_not_configured() {
});
}

/// Disabled by default, so a configured URL alone must not trigger a run.
#[test]
fn ocw_skips_when_disabled_even_with_url_configured() {
let mut ext = new_test_ext();
let (offchain, _) = TestOffchainExt::new();
ext.register_extension(OffchainWorkerExt::new(offchain.clone()));
ext.register_extension(OffchainDbExt::new(offchain));
let mut config_store = std::collections::HashMap::new();
config_store.insert(PROVER_DB_CONFIG_URL_KEY.to_string(), MOCK_URL.to_string());
ext.register_extension(native::config::ConfigExt(std::sync::Arc::new(config_store)));
ext.execute_with(|| {
System::set_block_number(1);
ProverDbIndexer::offchain_worker(1);
});
}

/// If another OCW round is in progress (lock held), this invocation
/// must do nothing — no HTTP traffic, no state reads beyond the lock
/// itself. `TestOffchainExt` would panic on an unexpected request, so
Expand Down
38 changes: 38 additions & 0 deletions sxt-core/src/prover_db_indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use url::Url;
use crate::tables::TableIdentifier;
use crate::IDENT_LENGTH;

/// Config key gating whether the prover-db OCW consumer runs at all; defaults to disabled.
pub const PROVER_DB_CONFIG_ENABLED_KEY: &str = "prover_db_indexer/enable";

/// Config key holding the prover-db indexer's target URL.
pub const PROVER_DB_CONFIG_URL_KEY: &str = "prover_db_indexer/url";

Expand Down Expand Up @@ -95,6 +98,14 @@ pub enum ProverDbConsumerConfigError {
}

impl ProverDbConsumerConfig {
/// Whether [`PROVER_DB_CONFIG_ENABLED_KEY`] is set to `true`; defaults to `false`.
pub fn enabled<F: Fn(&str) -> Option<Option<String>>>(get: F) -> bool {
get(PROVER_DB_CONFIG_ENABLED_KEY)
.flatten()
.and_then(|s| s.parse::<bool>().ok())
.unwrap_or(false)
}

/// Builds a config by looking up each setting via `get`, where
/// `get(key)` returns `None` if `key` isn't registered at all, or
/// `Some(None)` if it's registered but unset.
Expand Down Expand Up @@ -283,6 +294,33 @@ mod tests {
TableIdentifier::from_str_unchecked(name, namespace)
}

// ── ProverDbConsumerConfig::enabled ──────────────────────────────

#[test]
fn enabled_defaults_to_false() {
assert!(!ProverDbConsumerConfig::enabled(make_get(&[])));
assert!(!ProverDbConsumerConfig::enabled(make_get(&[(
PROVER_DB_CONFIG_ENABLED_KEY,
None,
)])));
assert!(!ProverDbConsumerConfig::enabled(make_get(&[(
PROVER_DB_CONFIG_ENABLED_KEY,
Some("not-a-bool"),
)])));
}

#[test]
fn enabled_true_when_explicitly_set() {
assert!(ProverDbConsumerConfig::enabled(make_get(&[(
PROVER_DB_CONFIG_ENABLED_KEY,
Some("true"),
)])));
assert!(!ProverDbConsumerConfig::enabled(make_get(&[(
PROVER_DB_CONFIG_ENABLED_KEY,
Some("false"),
)])));
}

// ── ProverDbConsumerConfig::try_from_map ─────────────────────────

/// Builds a `get` closure from an explicit key list. A key absent
Expand Down
Loading