Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
158 changes: 42 additions & 116 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions book/src/drive/average-index-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -1702,3 +1702,13 @@ The split closely parallels the count and sum chapters — point lookups for Q1
The chapter is grounded in the [`document_average_worst_case`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/benches/document_average_worst_case.rs) bench's measured numbers — Q1–Q7 verify cleanly end-to-end against the shared root hash `8b15f732…ffc7`.

A natural expansion follow-up (out of scope here): a worked example of "exact-precision" averages — for callers that need fractional averages (e.g. `avg = 50.7142857…` rather than `50.99`), the protocol-level approach is to return `(count, sum)` and let the client compute in its preferred numeric format (the chapter notes this in [Numerical Considerations](#numerical-considerations) above; a future expansion could walk through the fixed-point vs. floating-point trade-offs).

### No-proof path: joint count-and-sum dispatch

The no-proof AVG path lives in `crate::query::drive_document_count_and_sum_query`. It consumes the same `DocumentAverageRequest` the prove path uses and resolves routing through sum's versioned mode-detection table, so the `(where_clauses × mode)` → executor mapping has a single source of truth shared with the sum and count surfaces. The dispatcher splits on the resolved mode:

- **`Total` / `PerInValue`** (no-range `Equal`/`In` on a `summable + countable` index) walks the point-lookup path query and decodes `(count, sum)` from each visited `CountSumTree` terminator in one call via `Element::count_sum_value_or_default()`. One grovedb call per `In` branch, both metrics together.
- **`RangeNoProof` distinct shapes** (`GroupByRange` / `GroupByCompound` + range on an index that declares BOTH `rangeCountable: true` AND `rangeSummable: true` — DPP exposes `rangeAverageable: true` as shorthand for the pair) walk `ProvableCountProvableSumTree` terminators once via the same `distinct_sum_path_query` builder the sum surface uses, emitting one `(count, sum)` per distinct in-range key — strictly better than the count + sum surfaces' parallel walks because both metrics come from each visited element.
- **`RangeNoProof` aggregate shapes** (`Aggregate` / `GroupByIn` + range) call grovedb's combined merk-internal accumulator directly: `query_aggregate_count_and_sum` against the PCPS path query, yielding `(u64, i64)` from a single O(log n) traversal. Compound `In + range` per-In fans out (≤100 branches per the `In::in_values()` validator cap) and issues one accumulator call per branch under a shared read transaction. Bounded regardless of how many documents the range matches — keeping the public DAPI endpoint closed against amplification.

The no-prove combined accumulator (`query_aggregate_count_and_sum`) is the symmetric counterpart of the prove-side `AggregateCountAndSumOnRange` primitive Q5 / Q7 above use. Both sides walk the same PCPS terminator shape with `(u128, i128)` accumulators (narrowing to `(u64, i64)` at the entry point) — the only difference is that the no-prove path returns the pair directly while the prove path emits proof bytes the client verifies via `GroveDb::verify_aggregate_count_and_sum_query`.
2 changes: 1 addition & 1 deletion packages/rs-dpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ strum = { version = "0.26", features = ["derive"] }
json-schema-compatibility-validator = { path = '../rs-json-schema-compatibility-validator', optional = true }
once_cell = "1.19.0"
tracing = { version = "0.1.41" }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6", optional = true }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be", optional = true }

[dev-dependencies]
tokio = { version = "1.40", features = ["full"] }
Expand Down
4 changes: 2 additions & 2 deletions packages/rs-drive-abci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ derive_more = { version = "1.0", features = ["from", "deref", "deref_mut"] }
async-trait = "0.1.77"
console-subscriber = { version = "0.4", optional = true }
bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f", optional = true }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6" }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be" }
nonempty = "0.11"

[dev-dependencies]
Expand All @@ -103,7 +103,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [
drive = { path = "../rs-drive", features = ["fixtures-and-mocks"] }
drive-proof-verifier = { path = "../rs-drive-proof-verifier" }
strategy-tests = { path = "../strategy-tests" }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6", features = ["client"] }
grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be", features = ["client"] }
assert_matches = "1.5.0"
drive-abci = { path = ".", features = ["testing-config", "mocks"] }
bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f" }
Expand Down
12 changes: 6 additions & 6 deletions packages/rs-drive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ enum-map = { version = "2.0.3", optional = true }
intmap = { version = "3.0.1", features = ["serde"], optional = true }
chrono = { version = "0.4.35", optional = true }
itertools = { version = "0.13", optional = true }
grovedb = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6", optional = true, default-features = false }
grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6", optional = true }
grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6" }
grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6", optional = true }
grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6" }
grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "ad2492dcdc869a1452b0b10fbed8f9b0de1634c6" }
grovedb = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be", optional = true, default-features = false }
grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be", optional = true }
grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be" }
grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be", optional = true }
grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be" }
grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "9db515efe59602e536eb75e79308e0cf8f8474be" }

[dev-dependencies]
criterion = "0.5"
Expand Down
Loading
Loading