You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`SdkBuilder::with_proofs(false)` should govern every fetch surface. Callers who deliberately opt out of proofs (for cost or latency) should reach the unified `GetDocumentsCount` endpoint's no-proof modes (`Total` / `PerInValue` / `RangeNoProof`) via the same `Fetch` API the proof modes use.
Current Behavior
`DocumentCountQuery::TryFrom<...> for GetDocumentsCountRequest` hardcodes `prove: true` (`document_count_query.rs:206`). The blanket `impl Query for T` in `query.rs:119-124` does emit a `tracing::warn!` when `prove=false`, but the request still ships with `prove: true` on the wire. Effect:
Callers using `with_proofs(false)` get a fully-proven response with only a log-line indication of the divergence (the warning text says "ensure data is trusted," which is itself misleading since the data IS verified).
The server's no-proof execution paths — `Total` (O(1) reads on documents_countable contracts), `PerInValue` (one O(1) read per In value), `RangeNoProof` (per-In aggregate fan-out, O(|In| × log n)), and `RangeNoProof` distinct (O(limit × log n)) — are unreachable from the SDK.
PR #3623's review thread surfaced this as a deferred suggestion. The current state ships intentionally as "loud no-op + tracked follow-up."
Root cause (structural)
`Fetch::Request = DocumentCountQuery` and `FromProof::Request = DocumentCountQuery` — the same type implements both `TransportRequest` (for the gRPC transport) and serves as the input to the proof-decoder. The blanket `Query for T` thus owns the `prove` flag at `Fetch::fetch_with_metadata_and_proof`'s call to `query.query(sdk.prove())` (`fetch.rs:161`), and Rust's coherence rules block shadowing the blanket with a specific `impl Query for DocumentCountQuery` that could intercept `prove=false`.
The two structural fixes that don't fight coherence:
Split the transport vs. domain types. Stop implementing `TransportRequest` on `DocumentCountQuery`; implement `Query for DocumentCountQuery` instead. The custom `Query` impl owns the conversion + prove threading. Tricky because `FromProof::Request = DocumentCountQuery` carries the loaded `DataContract` context that `GetDocumentsCountRequest` doesn't have, and `Fetch::Request: IntoFromProof::Request` requires that conversion to roundtrip. Solvable, but invasive.
Add a no-proof decoder seam. Implement a parallel `Fetch`-shaped trait (or extend `Fetch`) that decodes the wire response's `Counts(...)` / `Entries(...)` variants directly without going through `FromProof`. `DocumentCount::fetch_unverified` and `DocumentSplitCounts::fetch_unverified` as named entry points, gated on `sdk.prove() == false`.
Possible Solution
(2) is the cleaner shape. Concretely:
Add a new SDK trait `FetchUnverified` (or method on `Fetch`) that takes `(sdk, query)` and returns the deserialized no-proof response directly.
For `DocumentCount`: `Fetch::fetch` switches on `sdk.prove()` — `true` → existing `FromProof` path; `false` → new no-proof decoder that extracts the `aggregate_count: u64` from the response's `Counts` oneof.
For `DocumentSplitCounts`: same switch, no-proof path extracts `entries: Vec` from the response's `Entries` oneof, builds `Vec`.
Wire the `prove` flag through to `TryFrom for GetDocumentsCountRequest` (probably by passing it as a field on `DocumentCountQuery` or via a fresh conversion method that takes it explicitly).
Once both decoders exist, the blanket `Query for T` warning becomes accurate (it really is unverified) and `with_proofs(false)` reaches the cheaper backend variants the server already supports.
Alternatives Considered
Hard-error on `prove=false`. The reviewer offered this as an alternative to the no-proof decoder. Cleaner than silent-ignore, but breaks callers who deliberately set `with_proofs(false)` SDK-wide for other queries and now have to special-case count queries.
Keep silent-ignore, accept the divergence. Status quo. Documented in `document_count_query.rs:185-206` as a no-op. Reviewer's "milder framing" framing accepts this as the current shipped state, but flags it as a real gap.
Cross-language SDKs (wasm-sdk, rs-sdk-ffi) already expose `return_distinct_counts_in_range` and related knobs but route through the same proof path; they'd benefit from a no-proof entry point too.
Pre-release scope means breaking the existing `Fetch`-routes-to-FromProof contract is on the table; post-release this would want a platform-version gate.
Expected Behavior
`SdkBuilder::with_proofs(false)` should govern every fetch surface. Callers who deliberately opt out of proofs (for cost or latency) should reach the unified `GetDocumentsCount` endpoint's no-proof modes (`Total` / `PerInValue` / `RangeNoProof`) via the same `Fetch` API the proof modes use.
Current Behavior
`DocumentCountQuery::TryFrom<...> for GetDocumentsCountRequest` hardcodes `prove: true` (`document_count_query.rs:206`). The blanket `impl Query for T` in `query.rs:119-124` does emit a `tracing::warn!` when `prove=false`, but the request still ships with `prove: true` on the wire. Effect:
PR #3623's review thread surfaced this as a deferred suggestion. The current state ships intentionally as "loud no-op + tracked follow-up."
Root cause (structural)
`Fetch::Request = DocumentCountQuery` and `FromProof::Request = DocumentCountQuery` — the same type implements both `TransportRequest` (for the gRPC transport) and serves as the input to the proof-decoder. The blanket `Query for T` thus owns the `prove` flag at `Fetch::fetch_with_metadata_and_proof`'s call to `query.query(sdk.prove())` (`fetch.rs:161`), and Rust's coherence rules block shadowing the blanket with a specific `impl Query for DocumentCountQuery` that could intercept `prove=false`.
The two structural fixes that don't fight coherence:
Split the transport vs. domain types. Stop implementing `TransportRequest` on `DocumentCountQuery`; implement `Query for DocumentCountQuery` instead. The custom `Query` impl owns the conversion + prove threading. Tricky because `FromProof::Request = DocumentCountQuery` carries the loaded `DataContract` context that `GetDocumentsCountRequest` doesn't have, and `Fetch::Request: IntoFromProof::Request` requires that conversion to roundtrip. Solvable, but invasive.
Add a no-proof decoder seam. Implement a parallel `Fetch`-shaped trait (or extend `Fetch`) that decodes the wire response's `Counts(...)` / `Entries(...)` variants directly without going through `FromProof`. `DocumentCount::fetch_unverified` and `DocumentSplitCounts::fetch_unverified` as named entry points, gated on `sdk.prove() == false`.
Possible Solution
(2) is the cleaner shape. Concretely:
Once both decoders exist, the blanket `Query for T` warning becomes accurate (it really is unverified) and `with_proofs(false)` reaches the cheaper backend variants the server already supports.
Alternatives Considered
Additional Context