Skip to content

feat(dpp): implement identity create transition#663

Closed
markin-io wants to merge 19 commits into
v0.24-devfrom
feat/implement_identity_create_st
Closed

feat(dpp): implement identity create transition#663
markin-io wants to merge 19 commits into
v0.24-devfrom
feat/implement_identity_create_st

Conversation

@markin-io
Copy link
Copy Markdown
Contributor

Issue being fixed or feature implemented

What was done?

How Has This Been Tested?

Breaking Changes

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone
@markin-io markin-io marked this pull request as draft December 12, 2022 16:52
@shumkov shumkov changed the title feat(wasm-dpp): implement identity create transition feat(dpp): implement identity create transition Dec 15, 2022
@markin-io markin-io closed this Jan 15, 2023
@shumkov shumkov deleted the feat/implement_identity_create_st branch May 10, 2023 10:04
QuantumExplorer added a commit that referenced this pull request May 15, 2026
…+ bench probe

Pulls in dashpay/grovedb#663 ("feat(grovedb,query): allow AggregateCountOnRange
as carrier subquery"), merge commit 87554188ad — bumps every pinned
`grovedb*` dep across the workspace from a917d92d to 87554188.

The new grovedb APIs:
- `Query::validate_carrier_aggregate_count_on_range`
- `Query::validate_leaf_aggregate_count_on_range`
- `GroveDb::query_aggregate_count_per_key`
- `GroveDb::verify_aggregate_count_query_per_key`

These unblock the chapter 30 G7 shape (`brand IN[...] AND color > floor` with
`group_by = [brand]`) at the grovedb layer. Drive wire-up is the next step
(lift mode_detection.rs:140 rejection + new path-query builder + new
DocumentCountMode variant + per-key verifier wrapper).

This commit also adds `probe_carrier_acor` to document_count_worst_case bench
as a feasibility smoke test against the existing 100 000-row widget fixture:

  [carrier-acor] no-proof entries (2):
    ("brand_000", 499)
    ("brand_001", 499)
  [carrier-acor] proof bytes: 4332 B
  [carrier-acor] verified root_hash: 0x62ee7348f4d28dd9d7cf86a6c725fa8276...
  [carrier-acor] verified entries (2):
    ("brand_000", 499)
    ("brand_001", 499)

4 332 B for k=2, matching the complexity estimate documented in chapter 30
(`O(k · (log B + log C'))`) and ~17 % smaller than the concatenated-leaf-ACOR
alternative.

Verification:
- cargo check --workspace clean
- cargo test -p drive --lib drive_document_count_query → 45 tests passing
- cargo test -p drive --lib verify → 240 tests passing
- All chapter 29 / chapter 30 proof sizes (585 / 1041 / 1327 / 1911 / 1102 /
  1381 / 2072 / 2656 B for Q1..Q8) unchanged — bump is purely additive
- Carrier-ACOR end-to-end: query → prove → verify all round-trip with root
  hash matching the chapter's known 0x62ee7348... fixture root

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request May 15, 2026
…r range)

Lifts the `mode_detection.rs:140` rejection for the `GroupByIn + In + range +
prove` case, now that grovedb PR #663 exposes `AggregateCountOnRange` as a
carrier subquery under outer `Keys`. The new shape returns one
`(in_key, u64)` per resolved In branch in a single proof:

  brand IN ["brand_000", "brand_001"] AND color > "color_00000500"
  group_by = [brand]   →  Entries([("brand_000", 499), ("brand_001", 499)])
                          Proof(4 332 bytes), median 255.9 µs

Drive-side wire-up
- New `DocumentCountMode::RangeAggregateCarrierProof` variant.
- `mode_detection::detect_mode`: rejection lifted for `CountMode::GroupByIn`
  carrying `(In + range)`; routes to the new mode. Aggregate-mode `In +
  range + prove` still rejected (no group_by means caller asks for a
  single sum, which carrier-ACOR can't safely produce without verifier
  trust in the SDK's summation).
- New `DriveDocumentCountQuery::carrier_aggregate_count_path_query` builder
  in `path_query.rs` — outer Keys per In value, subquery_path through the
  index's middle properties (`==` clauses) plus the terminator name,
  subquery is `Query::new_aggregate_count_on_range(range_item)`. Mirrors
  the In-fan-out pattern from `distinct_count_path_query` but with the
  carrier-ACOR subquery composition.
- New executor `Drive::execute_document_count_range_aggregate_carrier_proof`
  in `executors/range_aggregate_carrier_proof.rs`, plus inner
  `DriveDocumentCountQuery::execute_carrier_aggregate_count_with_proof`
  in `execute_range_count.rs`.
- New verifier `DriveDocumentCountQuery::verify_carrier_aggregate_count_proof`
  (`v0`) wrapping `GroveDb::verify_aggregate_count_query_per_key`. Returns
  `(RootHash, Vec<(Vec<u8>, u64)>)`.
- Added the new method version to
  `DriveVerifyDocumentCountMethodVersions` (defaults to `0` in `v1.rs`).
- Dispatcher arm in `drive_dispatcher.rs` matches the new mode and
  returns `DocumentCountResponse::Proof(...)`.

Bench
- Matrix entry `[brand] / where=brand IN[2] AND color > floor` flipped
  from rejected ("no — single-field GROUP BY with both `In` and range")
  to allowed ("yes (RangeAggregateCarrierProof — carrier ACOR per In
  branch)") with `prove: Proof(4 332 bytes)`.
- New `query_g7_brand_in_color_gt_grouped_by_brand` criterion bench —
  10 samples × 9 295 iters, median 255.87 µs (~4× Q8's 71 µs because
  it's two parallel Q8-shaped descents).
- New `G7` case in `display_group_by_proofs` emits the full 186-line
  carrier-ACOR proof verbatim as `[gproof] G7 [brand] / where=...`.

Chapter 30 (`book/src/drive/count-index-group-by-examples.md`)
- G7 added to the navigation table (`O(k · (log B + log C'))`, 255.9 µs,
  4 332 B, `Entries(2 groups, sum = 998)`).
- New "G7 — Carrier `In` + Range, Grouped By `brand`" section with the
  same template as G1..G6: path query, verified payload, proof size,
  proof display (schematic + interactive visualizer link), narrative,
  conceptual flowchart, per-layer (Layer-5+) merk-tree diagram.
- "Group-By Shapes That Are Not Allowed" section's bucket #4 removed
  (the "incoming" placeholder), replaced with a historical note
  pointing forward to G7.

Tests + verification
- `cargo test -p drive --lib drive_document_count_query` → 45 passing
- `cargo test -p drive --lib verify` → 240 passing
- All chapter 29 / chapter 30 documented proof sizes (Q1..Q8, G3..G6)
  unchanged — wire-up is purely additive on top of grovedb PR #663.
- mdBook builds clean.

Closes (in this PR): chapter 30 G7 placeholder.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request May 15, 2026
Adds `probe_carrier_acor_range_outer` — the natural extension of
`probe_carrier_acor` from `outer In` to `outer Range`. Confirms the
grovedb feature works for our widget fixture:

  [carrier-acor-range] probing: widget/brand RangeAfter(brand_050..)
                                subquery_path=color
                                subquery=AggregateCountOnRange(RangeAfter(color_00000500..))
  [carrier-acor-range] no-proof entries (49):
    ("brand_051", 499) … ("brand_099", 499)
  [carrier-acor-range] proof bytes: 84576 B
  [carrier-acor-range] verified root_hash: 0x62ee7348… (matches chapter fixture)
  [carrier-acor-range] verified entries (49):
    ("brand_051", 499) … ("brand_099", 499)

Findings worth recording:

1. The outer-Range carrier-ACOR shape WORKS at the grovedb layer
   (grovedb PR #663's `validate_carrier_aggregate_count_accepts_range_outer_items`
   covers this). The widget fixture's 49 brands > "brand_050" each
   carry the expected per-brand count of 499 colors > "color_00000500"
   (the bench's fixture has 1 doc per (brand, color) pair).

2. **`SizedQuery::limit` is rejected on any ACOR-bearing query**
   (carrier or leaf) — grovedb's validator returns
   `InvalidQuery("AggregateCountOnRange queries may not set SizedQuery::limit")`.
   So "limit the outer Range walk to N matches" can't be expressed
   today; this probe walks the full 49 brands and pays the resulting
   ~83 KB proof size. The natural drive-level workaround is to
   compute an explicit upper bound for the outer Range from the
   requested limit (e.g. rewrite `brand > X` with `limit = 20` to
   `brand > X AND brand <= caller_supplied_or_precomputed_Y`) — but
   that pushes the upper-bound responsibility to the caller or
   requires an extra grovedb read.

3. Drive doesn't wire this through yet: `mode_detection::detect_mode`
   rejects ≥2 range clauses up front ("count query supports at most
   one range where-clause"), independent of the limit issue. The
   shape is logged here as future work for chapter 30; lifting it
   requires both the multi-range-rejection in mode_detection AND a
   grovedb-level extension to support `SizedQuery::limit` on carrier
   ACOR (or a drive-level upper-bound computation).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request May 15, 2026
Targets grovedb PR #664 head (4e20c338) — the follow-up to PR #663 that
relaxes the leaf-strict `SizedQuery::limit` rule for carrier ACOR queries.

The new shape unblocks the `Q8`-with-outer-range case:

  brand > "brand_050" AND color > "color_00000500"
  group_by = [brand]
  limit = 20

  →  Entries([("brand_051", 499), …, ("brand_070", 499)])
     Proof(35 122 bytes), median 1.07 ms

The proof bytes scale linearly with `limit`: 20 outer matches × ~1 700 B
per per-brand ACOR boundary walk ≈ 35 KB, matching the per-In slope
established by Q8 vs G7.

Drive-side wire-up extending the existing `RangeAggregateCarrierProof`
mode:

- `mode_detection`: lifts `range_count > 1` for the specific shape
  (CountMode::GroupByRange + prove + exactly two range clauses on
  distinct fields + no In). Routes to the existing
  `DocumentCountMode::RangeAggregateCarrierProof` arm.
- `path_query::carrier_aggregate_count_path_query`: generalized to
  accept either an `In` clause (G7 shape) OR a range clause (G8
  shape) at the carrier position. The terminator's range becomes
  the inner ACOR `QueryItem`. Builder now takes `limit: Option<u16>`
  and threads it to `SizedQuery::new`.
- `execute_carrier_aggregate_count_with_proof`: accepts `limit`,
  passes through to the builder.
- `Drive::execute_document_count_range_aggregate_carrier_proof`:
  accepts `limit`, plumbs through.
- `drive_dispatcher`: extracts `request.limit`, validates against
  `max_query_limit` (same validate-don't-clamp policy as
  `RangeDistinctProof`), passes through.
- `verify_carrier_aggregate_count_proof[_v0]`: accepts `limit`,
  rebuilds the same `PathQuery` byte-for-byte.
- `index_picker::find_range_countable_index_for_where_clauses`:
  extended to accept the two-range case — finds an index whose
  first property carries one range (the outer carrier) and whose
  terminator carries the other (the inner ACOR). Single-range case
  is unchanged.
- `drive_dispatcher::where_clauses_from_value`: catches the system-
  wide parser's `MultipleRangeClauses` error for count queries.
  Structural validation lives in `detect_mode`; the regular-query
  parser's "all ranges must be on same field" rule was rejecting
  the G8 shape upstream.

Bench:
- Matrix entry `[brand] / where=brand > floor AND color > floor
  (limit 20)` flipped from rejected to `Proof(35 122 bytes)`.
- New `query_g8_brand_gt_color_gt_grouped_by_brand_limit_20`
  criterion bench — 10 samples × 5 060 iters, median 1.07 ms
  (~4× G7's 256 µs because the outer walk is 10× longer).
- New `G8` case in `display_group_by_proofs`.
- `probe_carrier_acor_range_outer` now uses `limit = 20` (was
  unbounded in the previous commit's feasibility probe). Proof
  shrinks from ~83 KB to 35 122 B.

Chapter 30:
- G8 row in the nav table (`O(L · (log B + log C'))`, 1 072 µs,
  35 122 B, `Entries(20 groups, sum = 9 980)`).
- New "G8 — Carrier outer Range + Range, Grouped By `brand`"
  section with the same template as G1..G7: path query, verified
  payload, schematic proof display + interactive visualizer link,
  conceptual flowchart, per-layer (Layer-5+) merk-tree diagram.
- Complexity variables note extends `k` (|IN|) with `L` (the
  caller's `limit` for the Range-outer carrier shape).

Tests + verification:
- cargo test -p drive --lib drive_document_count_query → 45 passing
- cargo test -p drive --lib verify → 240 passing
- All previously documented proof sizes unchanged (Q1..Q8 / G3..G7
  byte-identical to before)
- G8 end-to-end via the dispatcher matches the standalone grovedb-
  level probe (35 122 B; root hash 0x62ee7348… matches chapter
  fixture)
- mdBook builds clean

The grovedb rev points at PR #664's open head (4e20c338); will be
rebased to the merge commit once the PR lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request May 16, 2026
- v1 wire: add `DocumentFieldValue.null_value` variant so the
  typed surface can carry `null` operands the v0 CBOR shape
  supports (previously dropped). Conversions on both sides
  (rs-drive-abci `value_from_proto`, rs-sdk `value_to_proto`)
  + the test-only `pv` helper handle the variant.
- v1 routing: allow `group_by=[in_field]` and `group_by=[range_field]`
  alongside the other constraint — drive's `detect_mode` picks
  `RangeAggregateCarrierProof` (grovedb #663) on the prove path
  and `RangeNoProof` / `RangeDistinctProof` on the no-prove path.
  Both produce entries that match the caller's single-field
  GROUP BY. The two `reject_*` tests become `accept_*` tests.
- v0 abci handler: propagate `order_by` clause-parse errors
  instead of silently dropping malformed components.
- rs-drive `from_decomposed_values`: same tightening for the
  legacy CBOR `order_by` parse path — malformed clauses now
  reject the request rather than silently producing partial /
  default ordering.
- drive_dispatcher: fix `validate_and_canonicalize_where_clauses`
  docstring to accurately describe validation-only behavior on
  the worktree base (no `> AND <` → `between*` merge step).
- rs-sdk: destructure `dapi_request` in `TryFrom<DocumentQuery>`
  to drop the per-field `.clone()` calls.
- tests `pv` helper: narrow its docstring to the explicit subset
  of `Value` variants it handles, with a panic on others.

Regenerated dapi-grpc bindings: 8 files (web / nodejs / objc /
python) pick up the new `null_value` field.

Tests: 54 abci document_query + 48 drive count tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant