@dashevo/dapi-grpc 4.2.0-dev.7 → 4.2.0-dev.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashevo/dapi-grpc",
3
- "version": "4.2.0-dev.7",
3
+ "version": "4.2.0-dev.9",
4
4
  "description": "DAPI GRPC definition file and generated clients",
5
5
  "browser": "browser.js",
6
6
  "main": "node.js",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "homepage": "https://github.com/dashevo/dapi-grpc#readme",
47
47
  "dependencies": {
48
- "@dashevo/grpc-common": "4.2.0-dev.7",
48
+ "@dashevo/grpc-common": "4.2.0-dev.9",
49
49
  "@dashevo/protobufjs": "6.10.5",
50
50
  "@grpc/grpc-js": "^1.14.3",
51
51
  "@improbable-eng/grpc-web": "^0.15.0",
@@ -596,15 +596,15 @@ message GetDocumentsRequest {
596
596
  STARTS_WITH = 10;
597
597
  // Time-range bucket selection (v1 only; the v0 CBOR surface is
598
598
  // unaffected). `field` names a timestamp covered by a `timeRange`
599
- // index. Operand: `text` selector `"newest"`/`"oldest"` when one grid
600
- // buckets the field, or `list` `[selector, range, step(, phase)]` in
601
- // the contract's declared seconds to name one of several grids (zero
602
- // phase is spelled by omission one wire spelling per grid). The
603
- // server resolves it to a bucket-start equality from current block
604
- // time; the verifier re-derives the same bucket from the quorum-signed
605
- // metadata time an ordinary index/count proof. See `timeRange` in
606
- // the document meta-schema and
607
- // `drive::query::resolve_time_range_bucket_clause`.
599
+ // index. The operand is `WhereClause.time_range` (a
600
+ // `TimeRangeSelection`); `WhereClause.value` must be unset. For the
601
+ // relative selectors (`NEWEST` / `OLDEST`) the server resolves the
602
+ // selection to a bucket-start equality from current block time and
603
+ // the verifier re-derives the same bucket from the quorum-signed
604
+ // metadata time; `BY_START` names the window absolutely, so both
605
+ // sides read the start straight from the query an ordinary
606
+ // index/count proof either way. See `timeRange` in the document
607
+ // meta-schema and `drive::query::resolve_time_range_bucket_clause`.
608
608
  IN_TIME_RANGE = 11;
609
609
  }
610
610
 
@@ -658,6 +658,54 @@ message GetDocumentsRequest {
658
658
  }
659
659
  }
660
660
 
661
+ // Operand of an `IN_TIME_RANGE` where clause: which window of a
662
+ // `timeRange` grid the query selects. Typed rather than riding
663
+ // `DocumentFieldValue` — the selection is not a field value, and a
664
+ // structured message keeps the selector an enum instead of a
665
+ // magic string.
666
+ //
667
+ // The relative selectors are resolved server-side: `NEWEST` is the
668
+ // freshest started window (largest grid start <= block time; the
669
+ // latest partial slice of history), `OLDEST` the oldest window still
670
+ // active at block time (a near-full trailing window of ~`range` —
671
+ // best for "trending over the last window"). The proof verifier
672
+ // re-derives the same window from the quorum-signed response
673
+ // metadata time, so neither side trusts the other's clock.
674
+ //
675
+ // `BY_START` names a window absolutely — any window, current or
676
+ // historic — by its start. `start_ms` is then required and must lie
677
+ // on the grid (`start_ms == phase + k * step`, in milliseconds);
678
+ // an unaligned start is rejected rather than snapped. A window with
679
+ // no documents (including one that has not started yet) is a
680
+ // provable empty answer, not an error. The relative selectors must
681
+ // NOT carry `start_ms` — one wire spelling per meaning.
682
+ message TimeRangeSelection {
683
+ enum Selector {
684
+ NEWEST = 0;
685
+ OLDEST = 1;
686
+ BY_START = 2;
687
+ }
688
+ // Names one of the field's declared grids, in the contract's own
689
+ // seconds — verbatim from the contract's `timeRange` declaration.
690
+ // Required when more than one `timeRange` grid buckets the field
691
+ // (the bare selector is ambiguous there and rejected); optional
692
+ // while exactly one grid does. A zero `phase` is the proto3
693
+ // default, matching the contract grammar where `phase` is an
694
+ // omittable key — every grid has exactly one wire spelling by
695
+ // construction.
696
+ message Grid {
697
+ uint64 range = 1 [jstype = JS_STRING];
698
+ uint64 step = 2 [jstype = JS_STRING];
699
+ uint64 phase = 3 [jstype = JS_STRING];
700
+ }
701
+ Selector selector = 1;
702
+ // `BY_START` only: the selected window's start, as a millisecond
703
+ // timestamp on the grid (see the message docstring). Rejected on
704
+ // the relative selectors.
705
+ optional uint64 start_ms = 2 [jstype = JS_STRING];
706
+ Grid grid = 3;
707
+ }
708
+
661
709
  // Single `field <op> value` clause. The server reassembles a
662
710
  // `Vec<WhereClause>` from the request's `where_clauses` field,
663
711
  // runs the same `WhereClause::group_clauses` validator (rejects
@@ -666,10 +714,16 @@ message GetDocumentsRequest {
666
714
  // then hands the structured clauses to the executor. Wire
667
715
  // semantics are identical to v0's CBOR `[field, op, value]`
668
716
  // triples — only the envelope differs.
717
+ //
718
+ // Exactly one operand field is set, keyed by the operator:
719
+ // `operator = IN_TIME_RANGE` carries its operand in `time_range`
720
+ // (`value` must be unset); every other operator carries `value`
721
+ // (`time_range` must be unset). Either mismatch is rejected.
669
722
  message WhereClause {
670
723
  string field = 1;
671
724
  WhereOperator operator = 2;
672
725
  DocumentFieldValue value = 3;
726
+ TimeRangeSelection time_range = 4;
673
727
  }
674
728
 
675
729
  // Per-group aggregate operand for the left side of a
@@ -1158,6 +1212,127 @@ message GetDocumentsRequest {
1158
1212
  // no ranked executor. Cursor pagination via `start_after` /
1159
1213
  // `start_at` remains the supported way to page through documents.
1160
1214
  optional uint32 offset = 12;
1215
+
1216
+ // Chained mode — a provable semi-join:
1217
+ // `SELECT * FROM <outer_document_type> WHERE $id IN
1218
+ // (SELECT <join_property> FROM <document_type> WHERE ...)`.
1219
+ //
1220
+ // Presence of this message selects chained mode: this request's
1221
+ // own `document_type` / `where_clauses` / `order_by` / `limit`
1222
+ // describe the INNER indexOnly query, and the outer half is
1223
+ // DERIVED from its results — the request carries no outer
1224
+ // clauses by design, and the verifier re-derives the outer
1225
+ // query from the proven inner values, so the join cannot be
1226
+ // steered by the responding node.
1227
+ //
1228
+ // Mode gates (rejected otherwise): the inner type must be
1229
+ // indexOnly and resolve to an index carrying `join_property`;
1230
+ // `join_property` must declare a same-contract
1231
+ // `refersTo: permanentDocument` targeting
1232
+ // `outer_document_type`; `limit` is REQUIRED (it bounds the
1233
+ // derived outer query — no server-default fallback) and capped
1234
+ // by the outer `$id IN` clause's 100-value limit; `selects`
1235
+ // must be empty or a single DOCUMENTS projection; `group_by`,
1236
+ // `having`, time-range clauses, cursors, and `offset` are all
1237
+ // rejected. Pagination is a range clause on `join_property`.
1238
+ //
1239
+ // The verifier needs nothing beyond the proof itself: it
1240
+ // subset-verifies the inner query against the merged proof to
1241
+ // extract the join values, re-derives the outer component, and
1242
+ // verifies the whole composition. A node that predates this
1243
+ // field ignores it (proto3 unknown field) and serves the plain
1244
+ // inner query — which FAILS CLOSED client-side: an inner-only
1245
+ // proof cannot satisfy the re-derived merged query for a
1246
+ // non-empty page, and an unproven response carries the wrong
1247
+ // ResultData variant.
1248
+ message ChainedJoin {
1249
+ // The inner property whose proven values become the outer
1250
+ // documents' `$id`s.
1251
+ string join_property = 1;
1252
+ // The joined document type — the `refersTo` target.
1253
+ string outer_document_type = 2;
1254
+ }
1255
+ ChainedJoin chained = 13;
1256
+
1257
+ // Composite mode — a page plus sub-queries DERIVED from its
1258
+ // results, answered as ONE merged proof over one state root.
1259
+ //
1260
+ // Presence of any `sub_queries` selects composite mode: this
1261
+ // request's own `data_contract_id` / `document_type` /
1262
+ // `where_clauses` / `order_by` / `limit` describe the PAGE, and
1263
+ // every sub-query's `IN` clause is derived by the node from the
1264
+ // page's (or an earlier sub-query's) proven documents. The
1265
+ // verifier re-derives every sub-query from the proven page with
1266
+ // the same builders, re-merges, and verifies the whole
1267
+ // composition — so the composition cannot be steered by the
1268
+ // responding node, and a node that predates this field (proto3
1269
+ // unknown field) serves a page-only proof that FAILS CLOSED
1270
+ // client-side.
1271
+ //
1272
+ // Mode gates (rejected otherwise): `limit` is REQUIRED on the
1273
+ // page (at most 100 — it bounds every derived clause); `selects`
1274
+ // must be empty or a single DOCUMENTS projection; `group_by`,
1275
+ // `having`, time-range clauses, cursors and `offset` are
1276
+ // rejected (paginate with a range clause on the page's ordering
1277
+ // property); `chained` and `sub_queries` are mutually exclusive.
1278
+ // See `SubQuery` for the per-sub-query rules.
1279
+ message SubQuery {
1280
+ // The contract this sub-query targets. Empty = the page's own
1281
+ // contract; otherwise any contract (profiles keyed by owner,
1282
+ // names keyed by identity).
1283
+ bytes data_contract_id = 1;
1284
+ string document_type = 2;
1285
+ // The FIXED clauses — everything but the derived `IN`, which
1286
+ // must not be named here.
1287
+ repeated WhereClause where_clauses = 3;
1288
+ // Ordering (documents only). Every component of the merged proof
1289
+ // walks in the page's direction: a bound field missing from here
1290
+ // is appended in that direction by the node and the verifier
1291
+ // alike, and an ordering that disagrees with the page's direction
1292
+ // is refused (turning a limited lookup around would change the
1293
+ // rows it returns).
1294
+ repeated OrderClause order_by = 4;
1295
+ // Documents lookups on a non-unique index REQUIRE a limit: it
1296
+ // caps the rows the lookup returns in total, in walk order, like
1297
+ // an ordinary IN query's limit (at most 100). Lookups already
1298
+ // bounded by their values (a unique index, or an indexOnly
1299
+ // terminal with every prefix fixed), by-id joins (completeness is
1300
+ // set equality) and counts take none.
1301
+ optional uint32 limit = 5;
1302
+ enum Kind {
1303
+ // The matching documents.
1304
+ DOCUMENTS = 0;
1305
+ // One count per derived value from the `countable` index
1306
+ // covering the fixed clauses plus the bound field. Must be
1307
+ // bound, and must not share its index path with a documents
1308
+ // component (the count reads the value trees the documents
1309
+ // query descends past).
1310
+ COUNT = 1;
1311
+ }
1312
+ Kind kind = 6;
1313
+ // The derived clause `<field> IN <values>`. Absent = a SIBLING:
1314
+ // an independent documents query proven under the same root.
1315
+ message Binding {
1316
+ // Whose proven documents supply the values: `0` = the page,
1317
+ // `n` = `sub_queries[n - 1]` (which must precede this one and
1318
+ // be a DOCUMENTS sub-query).
1319
+ uint32 source = 1;
1320
+ // The source property read off each document: `$id`,
1321
+ // `$ownerId`, or an identifier-typed property (dotted paths
1322
+ // reach nested properties). Documents without it contribute
1323
+ // nothing.
1324
+ string source_property = 2;
1325
+ // The sub-query field receiving the `IN` clause. `$id` makes
1326
+ // this a by-id JOIN: the source property must then declare
1327
+ // `refersTo: permanentDocument` targeting this document type,
1328
+ // so every derived id resolves and a missing document is an
1329
+ // invalid proof. Otherwise `$ownerId` or an indexed property
1330
+ // (a LOOKUP, where absence is a proven fact).
1331
+ string field = 3;
1332
+ }
1333
+ Binding bind = 7;
1334
+ }
1335
+ repeated SubQuery sub_queries = 14;
1161
1336
  }
1162
1337
 
1163
1338
  oneof version {
@@ -1503,7 +1678,44 @@ message GetDocumentsResponse {
1503
1678
  // `skipped` carries the page's starting rank — see
1504
1679
  // `RankedEntries`.
1505
1680
  RankedEntries ranked = 5;
1681
+ // Chained-mode result: both halves of the provable
1682
+ // semi-join, in inner order (the last inner projection's
1683
+ // join-property value is the pagination cursor; outer
1684
+ // documents are ordered by first appearance of their id
1685
+ // among the inner projections, deduplicated). Routed when
1686
+ // the request's `chained` message is present.
1687
+ ChainedDocuments chained = 6;
1688
+ // Composite-mode result: the page plus one result per
1689
+ // sub-query, in request order. Routed when the request
1690
+ // carries `sub_queries`.
1691
+ CompositeDocuments composite = 7;
1692
+ }
1693
+ }
1694
+
1695
+ // Both halves of a chained (semi-join) query, each serialized
1696
+ // with its own document type.
1697
+ message ChainedDocuments {
1698
+ repeated bytes inner_documents = 1;
1699
+ repeated bytes outer_documents = 2;
1700
+ }
1701
+
1702
+ // A composite query's page and per-sub-query results, documents
1703
+ // serialized with their own document type.
1704
+ message CompositeDocuments {
1705
+ // The page, exactly as the page query alone would return it.
1706
+ repeated bytes page_documents = 1;
1707
+ message SubQueryResult {
1708
+ oneof result {
1709
+ // DOCUMENTS: a by-id join in first-appearance order of the
1710
+ // derived ids; a lookup or sibling in query order.
1711
+ Documents documents = 1;
1712
+ // COUNT: one entry per derived value that has a count tree
1713
+ // (a value with no entry counts zero), keyed by the
1714
+ // value's index-key bytes.
1715
+ CountEntries counts = 2;
1716
+ }
1506
1717
  }
1718
+ repeated SubQueryResult sub_results = 2;
1507
1719
  }
1508
1720
 
1509
1721
  oneof result {