From e0f6641ea140f6924b59ac6e8310ba01e8ee4c3d Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 13 Aug 2026 22:12:15 +0700 Subject: [PATCH 1/5] feat(drive): IN over pinned prefix properties on ranked and having-range queries A compound ranked index's leading properties can now carry at most one IN where clause (2..=10 distinct elements, null legal for the absent-value prefix) alongside equality pins, on both the ranked top-k and having-range surfaces. Each element selects its own prefix branch; the executors walk one axis secondary per branch with the full limit and merge deterministically by (aggregate in walk direction, encoded prefix segment ascending, group key in walk direction). Merged entries carry an in_key discriminator - the encoded segment of their branch - since one group key can legally appear under two prefixes. Proofs stay per-branch: the proved response is a versioned container of grovedb indexed-axis proofs in canonical branch order, and the verifier re-derives the branch set from its own resolution, verifies each branch against its own path, requires one root hash across branches, and re-merges with the shared comparator - the merge itself needs no proof because the merged page is a deterministic function of independently proved branch pages (any union entry preceding a returned entry is preceded within its own branch by fewer than limit entries, so per-branch completeness composes). A single-element IN is normalized to an equality pin and stays byte-identical to ==. OFFSET is rejected together with IN (rank-skip is attested from one secondary's counted commitments; no counted structure spans the union). Wire: RankedEntry gains optional in_key (additive; clients regenerated); no request-side changes. The branch ceiling is a hard rejection like the limit ceiling, since the branch set is echoed in the proof container. Grammar, merge order (including a cross-prefix aggregate tie and a null element mixed with a real one), the container tamper matrix (reorder / drop / duplicate / re-version / pad), the degenerate single-element equivalence, and the wire round trip are all pinned in the drive and abci suites. Co-Authored-By: Claude Fable 5 --- book/src/drive/document-ranked-trees.md | 4 +- .../clients/drive/v0/nodejs/drive_pbjs.js | 34 +- .../platform/v0/nodejs/platform_pbjs.js | 34 +- .../platform/v0/nodejs/platform_protoc.js | 74 +- .../platform/v0/objective-c/Platform.pbobjc.h | 18 +- .../platform/v0/objective-c/Platform.pbobjc.m | 11 + .../platform/v0/python/platform_pb2.py | 1239 +++++++++-------- .../clients/platform/v0/web/platform_pb.d.ts | 8 + .../clients/platform/v0/web/platform_pb.js | 74 +- .../protos/platform/v0/platform.proto | 12 +- .../query/document_query/v1/dispatch/mod.rs | 4 + .../src/query/document_query/v1/tests.rs | 84 +- .../src/proof/document_having.rs | 1 + .../src/proof/document_ranked.rs | 9 + .../v0/tests/batched_group_drain.rs | 2 +- .../v0/tests/ranked_index_e2e_tests.rs | 2 +- .../execute_range.rs | 65 +- .../query/drive_document_having_query/mod.rs | 48 +- .../mode_detection/v0/mod.rs | 16 +- .../drive_document_having_query/tests.rs | 218 ++- .../drive_document_ranked_query/branches.rs | 194 +++ .../execute_top_k.rs | 77 +- .../index_picker.rs | 142 +- .../query/drive_document_ranked_query/mod.rs | 77 +- .../mode_detection/mod.rs | 2 +- .../mode_detection/v0/mod.rs | 138 +- .../query/drive_document_ranked_query/path.rs | 7 +- .../drive_document_ranked_query/tests.rs | 412 +++++- .../verify_having_range_proof/v0/mod.rs | 55 +- .../verify_ranked_top_k_proof/v0/mod.rs | 65 +- packages/rs-sdk/src/mock/requests.rs | 21 +- 31 files changed, 2329 insertions(+), 818 deletions(-) create mode 100644 packages/rs-drive/src/query/drive_document_ranked_query/branches.rs diff --git a/book/src/drive/document-ranked-trees.md b/book/src/drive/document-ranked-trees.md index 6197c622352..85cc2d34c8e 100644 --- a/book/src/drive/document-ranked-trees.md +++ b/book/src/drive/document-ranked-trees.md @@ -91,7 +91,7 @@ One asymmetry is worth knowing when authoring: **the meta-schema demands the lit Two structural rules, both enforced at contract-parse time in rs-dpp: -- **No aggregating index on a compound ranked index's full prefix.** Ranked flags are allowed on compound indexes, with **per-prefix** semantics: a ranked `[identityId, class]` puts the indexed tree at each prefix value's terminal `class` property-name level — one ordered secondary per `identityId`, each ranking only that identity's `class` groups. There is deliberately no global cross-prefix ordering; the query surfaces require every leading property to be pinned by an equality `where` clause. The one shape that stays impossible — and is rejected per document type, where all indexes are visible (`validate_no_ranked_prefix_overlap`) — is a countable/summable index terminating at exactly the compound's leading prefix: its aggregating value trees would demand the `NonCounted` / `NotSummed` shell around the ranked terminal tree, and the storage layer structurally rejects any wrapper around an indexed tree, because the wrapper would neutralise the very aggregates the secondaries order by. (Drive's fail-closed guard behind the parse-time check is `INDEXED_INNER_UNWRAPPABLE`.) Only the exact `n-1` prefix conflicts: an aggregating index at a shorter prefix wraps a plain intermediate tree, and one extending past the ranked terminal lives inside its value trees — both supported. +- **No aggregating index on a compound ranked index's full prefix.** Ranked flags are allowed on compound indexes, with **per-prefix** semantics: a ranked `[identityId, class]` puts the indexed tree at each prefix value's terminal `class` property-name level — one ordered secondary per `identityId`, each ranking only that identity's `class` groups. There is deliberately no global cross-prefix ordering; the query surfaces require every leading property to be pinned by a `where` clause — equalities, plus at most one `IN` that fans out across prefix branches and merges deterministically. The one shape that stays impossible — and is rejected per document type, where all indexes are visible (`validate_no_ranked_prefix_overlap`) — is a countable/summable index terminating at exactly the compound's leading prefix: its aggregating value trees would demand the `NonCounted` / `NotSummed` shell around the ranked terminal tree, and the storage layer structurally rejects any wrapper around an indexed tree, because the wrapper would neutralise the very aggregates the secondaries order by. (Drive's fail-closed guard behind the parse-time check is `INDEXED_INNER_UNWRAPPABLE`.) Only the exact `n-1` prefix conflicts: an aggregating index at a shorter prefix wraps a plain intermediate tree, and one extending past the ranked terminal lives inside its value trees — both supported. - **Non-unique indexes only.** `ranked aggregates are not supported on unique indexes: each group of a unique index contains at most one document, so there is nothing meaningful to rank`. Contested indexes are covered transitively — a contested index is unique by construction, so it hits the same check rather than needing its own. ### Version Gate @@ -341,7 +341,7 @@ Note that the fixture puts each shape on its **own document type**. That's not a | Top / bottom K groups by sum of a property | `rankedSummable: true` on an index with `summable: ""` + `rangeSummable: true` | | Top / bottom K groups by average of a property | `rankedAverageable: true` on an index with `averageable: ""` + `rangeAverageable: true` (or the count+sum longhand) | | Two rankings on one index (e.g. by count *and* by average) | Both keywords. The tree is a PCPSIT carrying both axes in its TLV; you pay one secondary Merk per axis on every write. | -| A ranking filtered by another property (`top 5 restaurants in London`) | A **compound ranked index** with the filter property leading: `[city, restaurantId]` with the ranked flags. Each city gets its own secondary; the query pins the prefix with an equality `where` (`WHERE city == "London" GROUP BY restaurantId ORDER BY DESC LIMIT 5`). Only equality pins — a range or `IN` on the prefix is rejected, and there is no cross-prefix (global) ordering on a compound ranked index. | +| A ranking filtered by another property (`top 5 restaurants in London`) | A **compound ranked index** with the filter property leading: `[city, restaurantId]` with the ranked flags. Each city gets its own secondary; the query pins the prefix with an equality `where` (`WHERE city == "London" GROUP BY restaurantId ORDER BY DESC LIMIT 5`). Equality pins select one prefix; at most one pin may be an `IN` (2..=10 distinct elements, `null` legal for the absent-value prefix), which walks one secondary per element and merges by `(aggregate, encoded prefix, group key)` with per-branch proofs in one container — entries then carry `in_key`. A range operator on the prefix stays rejected, `OFFSET` is rejected together with `IN`, and there is still no global cross-prefix ordering beyond that merge. | | A ranking on a unique or contested index | Not available, and not meaningful: every group holds at most one document. | | Range aggregates without ranking (the 4.0 surface) | Just the `range*` flags. Ranking is strictly additive — adding it never changes what a range query returns. | | Nothing ranking-aware (default) | Don't set any `ranked*` flag. The terminal property-name tree keeps the type its range flags give it. | diff --git a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js index 0d1e656f487..5a97b6905be 100644 --- a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js +++ b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js @@ -26727,6 +26727,7 @@ $root.org = (function() { * @property {number|Long|null} [count] RankedEntry count * @property {number|Long|null} [sum] RankedEntry sum * @property {number|null} [avg] RankedEntry avg + * @property {Uint8Array|null} [inKey] RankedEntry inKey */ /** @@ -26776,6 +26777,14 @@ $root.org = (function() { */ RankedEntry.prototype.avg = 0; + /** + * RankedEntry inKey. + * @member {Uint8Array} inKey + * @memberof org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry + * @instance + */ + RankedEntry.prototype.inKey = $util.newBuffer([]); + // OneOf field names bound to virtual getters and setters var $oneOfFields; @@ -26822,6 +26831,8 @@ $root.org = (function() { writer.uint32(/* id 3, wireType 0 =*/24).sint64(message.sum); if (message.avg != null && Object.hasOwnProperty.call(message, "avg")) writer.uint32(/* id 4, wireType 1 =*/33).double(message.avg); + if (message.inKey != null && Object.hasOwnProperty.call(message, "inKey")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.inKey); return writer; }; @@ -26868,6 +26879,9 @@ $root.org = (function() { case 4: message.avg = reader.double(); break; + case 5: + message.inKey = reader.bytes(); + break; default: reader.skipType(tag & 7); break; @@ -26926,6 +26940,9 @@ $root.org = (function() { if (typeof message.avg !== "number") return "avg: number expected"; } + if (message.inKey != null && message.hasOwnProperty("inKey")) + if (!(message.inKey && typeof message.inKey.length === "number" || $util.isString(message.inKey))) + return "inKey: buffer expected"; return null; }; @@ -26966,6 +26983,11 @@ $root.org = (function() { message.sum = new $util.LongBits(object.sum.low >>> 0, object.sum.high >>> 0).toNumber(); if (object.avg != null) message.avg = Number(object.avg); + if (object.inKey != null) + if (typeof object.inKey === "string") + $util.base64.decode(object.inKey, message.inKey = $util.newBuffer($util.base64.length(object.inKey)), 0); + else if (object.inKey.length >= 0) + message.inKey = object.inKey; return message; }; @@ -26982,7 +27004,7 @@ $root.org = (function() { if (!options) options = {}; var object = {}; - if (options.defaults) + if (options.defaults) { if (options.bytes === String) object.key = ""; else { @@ -26990,6 +27012,14 @@ $root.org = (function() { if (options.bytes !== Array) object.key = $util.newBuffer(object.key); } + if (options.bytes === String) + object.inKey = ""; + else { + object.inKey = []; + if (options.bytes !== Array) + object.inKey = $util.newBuffer(object.inKey); + } + } if (message.key != null && message.hasOwnProperty("key")) object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; if (message.count != null && message.hasOwnProperty("count")) { @@ -27013,6 +27043,8 @@ $root.org = (function() { if (options.oneofs) object.value = "avg"; } + if (message.inKey != null && message.hasOwnProperty("inKey")) + object.inKey = options.bytes === String ? $util.base64.encode(message.inKey, 0, message.inKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.inKey) : message.inKey; return object; }; diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js index 978be7d0743..24f1ed1c9cd 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -26219,6 +26219,7 @@ $root.org = (function() { * @property {number|Long|null} [count] RankedEntry count * @property {number|Long|null} [sum] RankedEntry sum * @property {number|null} [avg] RankedEntry avg + * @property {Uint8Array|null} [inKey] RankedEntry inKey */ /** @@ -26268,6 +26269,14 @@ $root.org = (function() { */ RankedEntry.prototype.avg = 0; + /** + * RankedEntry inKey. + * @member {Uint8Array} inKey + * @memberof org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry + * @instance + */ + RankedEntry.prototype.inKey = $util.newBuffer([]); + // OneOf field names bound to virtual getters and setters var $oneOfFields; @@ -26314,6 +26323,8 @@ $root.org = (function() { writer.uint32(/* id 3, wireType 0 =*/24).sint64(message.sum); if (message.avg != null && Object.hasOwnProperty.call(message, "avg")) writer.uint32(/* id 4, wireType 1 =*/33).double(message.avg); + if (message.inKey != null && Object.hasOwnProperty.call(message, "inKey")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.inKey); return writer; }; @@ -26360,6 +26371,9 @@ $root.org = (function() { case 4: message.avg = reader.double(); break; + case 5: + message.inKey = reader.bytes(); + break; default: reader.skipType(tag & 7); break; @@ -26418,6 +26432,9 @@ $root.org = (function() { if (typeof message.avg !== "number") return "avg: number expected"; } + if (message.inKey != null && message.hasOwnProperty("inKey")) + if (!(message.inKey && typeof message.inKey.length === "number" || $util.isString(message.inKey))) + return "inKey: buffer expected"; return null; }; @@ -26458,6 +26475,11 @@ $root.org = (function() { message.sum = new $util.LongBits(object.sum.low >>> 0, object.sum.high >>> 0).toNumber(); if (object.avg != null) message.avg = Number(object.avg); + if (object.inKey != null) + if (typeof object.inKey === "string") + $util.base64.decode(object.inKey, message.inKey = $util.newBuffer($util.base64.length(object.inKey)), 0); + else if (object.inKey.length >= 0) + message.inKey = object.inKey; return message; }; @@ -26474,7 +26496,7 @@ $root.org = (function() { if (!options) options = {}; var object = {}; - if (options.defaults) + if (options.defaults) { if (options.bytes === String) object.key = ""; else { @@ -26482,6 +26504,14 @@ $root.org = (function() { if (options.bytes !== Array) object.key = $util.newBuffer(object.key); } + if (options.bytes === String) + object.inKey = ""; + else { + object.inKey = []; + if (options.bytes !== Array) + object.inKey = $util.newBuffer(object.inKey); + } + } if (message.key != null && message.hasOwnProperty("key")) object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; if (message.count != null && message.hasOwnProperty("count")) { @@ -26505,6 +26535,8 @@ $root.org = (function() { if (options.oneofs) object.value = "avg"; } + if (message.inKey != null && message.hasOwnProperty("inKey")) + object.inKey = options.bytes === String ? $util.base64.encode(message.inKey, 0, message.inKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.inKey) : message.inKey; return object; }; diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js index 10f2641e792..6bb7e0ddfde 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -30659,7 +30659,8 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank key: msg.getKey_asB64(), count: jspb.Message.getFieldWithDefault(msg, 2, "0"), sum: jspb.Message.getFieldWithDefault(msg, 3, "0"), - avg: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0) + avg: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), + inKey: msg.getInKey_asB64() }; if (includeInstance) { @@ -30712,6 +30713,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank var value = /** @type {number} */ (reader.readDouble()); msg.setAvg(value); break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setInKey(value); + break; default: reader.skipField(); break; @@ -30769,6 +30774,13 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank f ); } + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 5)); + if (f != null) { + writer.writeBytes( + 5, + f + ); + } }; @@ -30922,6 +30934,66 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank }; +/** + * optional bytes in_key = 5; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes in_key = 5; + * This is a type-conversion wrapper around `getInKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getInKey())); +}; + + +/** + * optional bytes in_key = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getInKey()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getInKey())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.setInKey = function(value) { + return jspb.Message.setField(this, 5, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.clearInKey = function() { + return jspb.Message.setField(this, 5, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.hasInKey = function() { + return jspb.Message.getField(this, 5) != null; +}; + + /** * List of repeated fields within this message type. diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h index c4e66dadcb9..0493c694fa5 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h @@ -2941,11 +2941,11 @@ typedef GPB_ENUM(GetDocumentsRequest_GetDocumentsRequestV1_Start_OneOfCase) { * - a is the In field AND b is the range field, in that order → existing compound distinct shape; entries carry both `in_key` (= a's value) and `key` (= b's value). * * `select=, group_by=[p], order_by=[]` (protocol v14+) — **ranked mode**: - * - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned with an `EQUAL` where clause (one per property, `group_by` names the trailing property), selecting which prefix's ranking is read. + * - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned (one clause per property, `group_by` names the trailing property) — `EQUAL` pins one prefix, and **at most one** clause may be `IN` (2..=10 distinct elements, `null` legal), fanning the walk out across one prefix branch per element and merging by `(aggregate, encoded prefix, group key)`; merged entries carry `in_key`. `offset` is rejected together with `IN` (rank-skip is per-secondary). * - `DESC` is the "top n" reading (walk the axis from the largest aggregate down), `ASC` the "bottom n" reading. Worked example: `SELECT AVG(grade) GROUP BY restaurantId ORDER BY grade DESC LIMIT 1 OFFSET 4` is the 5th-best restaurant. * * `select=, group_by=[p], having=[ ]` (protocol v14+) — **having-range mode**: - * - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one `EQUAL` pin per leading index property on a compound ranked index. + * - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one pin per leading index property on a compound ranked index, at most one of them an `IN` (2..=10 distinct elements) that fans the bound out across prefix branches and merges, entries carrying `in_key`. * - no offset or cursor pagination: a page cut at `limit` continues only by tightening the bound past the last *distinct* aggregate value seen; a cut inside a tie (several groups sharing the boundary aggregate) cannot be continued, so size `limit` above the widest expected tie. * * **Rejected shapes** (return `Unsupported`): @@ -3713,6 +3713,7 @@ typedef GPB_ENUM(GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNu GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNumber_Count = 2, GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNumber_Sum = 3, GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNumber_Avg = 4, + GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNumber_InKey = 5, }; typedef GPB_ENUM(GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_Value_OneOfCase) { @@ -3797,6 +3798,19 @@ GPB_FINAL @interface GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry : G **/ @property(nonatomic, readwrite) double avg; +/** + * The prefix branch this entry came from, set **only** on an + * `IN`-pinned request (see the supported-shape table): the + * encoded index-key bytes of the `IN` property's pinned value — + * empty bytes for the `null` (absent-value) branch. Absent on + * single-prefix responses. The same group key can legally appear + * under two prefixes, so `(in_key, key)` is the entry's identity + * on a merged page, exactly as on `CountEntry`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSData *inKey; +/** Test to see if @c inKey has been set. */ +@property(nonatomic, readwrite) BOOL hasInKey; + @end /** diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m index dd6f5cb79a7..1fc071948a7 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m @@ -7164,10 +7164,12 @@ @implementation GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry @dynamic count; @dynamic sum; @dynamic avg; +@dynamic hasInKey, inKey; typedef struct GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry__storage_ { uint32_t _has_storage_[2]; NSData *key; + NSData *inKey; uint64_t count; int64_t sum; double avg; @@ -7215,6 +7217,15 @@ + (GPBDescriptor *)descriptor { .flags = GPBFieldOptional, .dataType = GPBDataTypeDouble, }, + { + .name = "inKey", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry_FieldNumber_InKey, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry__storage_, inKey), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[GetDocumentsResponse_GetDocumentsResponseV1_RankedEntry class] diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py index 004bbbe6f33..3b9126ce2e0 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py @@ -23,7 +23,7 @@ syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xde\x15\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x12R\n\x02v1\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1H\x00\x1a\xfe\x02\n\x12\x44ocumentFieldValue\x12\x14\n\nbool_value\x18\x01 \x01(\x08H\x00\x12\x19\n\x0bint64_value\x18\x02 \x01(\x12\x42\x02\x30\x01H\x00\x12\x1a\n\x0cuint64_value\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04text\x18\x05 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x06 \x01(\x0cH\x00\x12[\n\x04list\x18\x07 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue.ValueListH\x00\x12\x14\n\nnull_value\x18\x08 \x01(\x08H\x00\x1a^\n\tValueList\x12Q\n\x06values\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueB\t\n\x07variant\x1a\xbe\x01\n\x0bWhereClause\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12N\n\x08operator\x18\x02 \x01(\x0e\x32<.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereOperator\x12P\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x1a\xa4\x01\n\x0fHavingAggregate\x12Y\n\x08\x66unction\x18\x01 \x01(\x0e\x32G.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\'\n\x08\x46unction\x12\t\n\x05\x43OUNT\x10\x00\x12\x07\n\x03SUM\x10\x01\x12\x07\n\x03\x41VG\x10\x02\x1a\xf9\x03\n\x0cHavingClause\x12Q\n\taggregate\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate\x12V\n\x08operator\x18\x02 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause.Operator\x12R\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueH\x00\"\xe0\x01\n\x08Operator\x12\t\n\x05\x45QUAL\x10\x00\x12\r\n\tNOT_EQUAL\x10\x01\x12\x10\n\x0cGREATER_THAN\x10\x02\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x03\x12\r\n\tLESS_THAN\x10\x04\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x05\x12\x0b\n\x07\x42\x45TWEEN\x10\x06\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x07\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x08\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\t\x12\x06\n\x02IN\x10\nB\x07\n\x05right\x1a\x90\x01\n\x0bOrderClause\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x12S\n\taggregate\x18\x03 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregateH\x00\x12\x11\n\tascending\x18\x02 \x01(\x08\x42\x08\n\x06target\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\x1a\xf3\x05\n\x15GetDocumentsRequestV1\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x12\\\n\x07selects\x18\t \x03(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select\x12\x10\n\x08group_by\x18\n \x03(\t\x12K\n\x06having\x18\x0b \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause\x12\x13\n\x06offset\x18\x0c \x01(\rH\x02\x88\x01\x01\x1a\xc9\x01\n\x06Select\x12\x66\n\x08\x66unction\x18\x01 \x01(\x0e\x32T.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"H\n\x08\x46unction\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x12\x07\n\x03SUM\x10\x02\x12\x07\n\x03\x41VG\x10\x03\x12\x07\n\x03MIN\x10\x04\x12\x07\n\x03MAX\x10\x05\x42\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xe7\x01\n\rWhereOperator\x12\t\n\x05\x45QUAL\x10\x00\x12\x10\n\x0cGREATER_THAN\x10\x01\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x04\x12\x0b\n\x07\x42\x45TWEEN\x10\x05\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x06\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x07\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\x08\x12\x06\n\x02IN\x10\t\x12\x0f\n\x0bSTARTS_WITH\x10\nB\t\n\x07version\"\xe7\x15\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x12T\n\x02v1\x18\x02 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\x1a\xf9\x11\n\x16GetDocumentsResponseV1\x12\x61\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ResultDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x1aL\n\nCountEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07_in_key\x1ar\n\x0c\x43ountEntries\x12\x62\n\x07\x65ntries\x18\x01 \x03(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntry\x1a\xa0\x01\n\x0c\x43ountResults\x12\x1d\n\x0f\x61ggregate_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x66\n\x07\x65ntries\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x42\t\n\x07variant\x1aH\n\x08SumEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x0f\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1an\n\nSumEntries\x12`\n\x07\x65ntries\x18\x01 \x03(\x0b\x32O.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntry\x1a\x9a\x01\n\nSumResults\x12\x1b\n\raggregate_sum\x18\x01 \x01(\x12\x42\x02\x30\x01H\x00\x12\x64\n\x07\x65ntries\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntriesH\x00\x42\t\n\x07variant\x1a_\n\x0c\x41verageEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x04 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1av\n\x0e\x41verageEntries\x12\x64\n\x07\x65ntries\x18\x01 \x03(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntry\x1a\x36\n\x10\x41verageAggregate\x12\x11\n\x05\x63ount\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x02 \x01(\x12\x42\x02\x30\x01\x1a\xfb\x01\n\x0e\x41verageResults\x12t\n\x11\x61ggregate_average\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageAggregateH\x00\x12h\n\x07\x65ntries\x18\x02 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntriesH\x00\x42\t\n\x07variant\x1aZ\n\x0bRankedEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\x13\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x11\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01H\x00\x12\r\n\x03\x61vg\x18\x04 \x01(\x01H\x00\x42\x07\n\x05value\x1a\x9a\x01\n\rRankedEntries\x12\x63\n\x07\x65ntries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry\x12\x18\n\x07skipped\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_skipped\x1a\x9b\x04\n\nResultData\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountResultsH\x00\x12\x61\n\x04sums\x18\x03 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumResultsH\x00\x12i\n\x08\x61verages\x18\x04 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageResultsH\x00\x12\x66\n\x06ranked\x18\x05 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntriesH\x00\x42\t\n\x07variantB\x08\n\x06resultB\t\n\x07version\"\xf4\x02\n\x19GetDocumentHistoryRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0H\x00\x1a\xeb\x01\n\x1bGetDocumentHistoryRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x03 \x01(\x0c\x12+\n\x05limit\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x07 \x01(\x08\x42\t\n\x07version\"\xf7\x04\n\x1aGetDocumentHistoryResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0H\x00\x1a\xeb\x03\n\x1cGetDocumentHistoryResponseV0\x12~\n\x10\x64ocument_history\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x14\x44ocumentHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\x95\x01\n\x0f\x44ocumentHistory\x12\x81\x01\n\x10\x64ocument_entries\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xbc\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x9b\x04\n#GetShieldedEncryptedNotesResponseV0\x12\x8a\x01\n\x0f\x65ncrypted_notes\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aW\n\rEncryptedNote\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x0b\n\x03\x63mx\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65ncrypted_note\x18\x03 \x01(\x0c\x12\x0e\n\x06\x63v_net\x18\x04 \x01(\x0c\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc0\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1a/\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd3\x02\n\x1dGetShieldedNotesCountResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse.GetShieldedNotesCountResponseV0H\x00\x1a\xbe\x01\n\x1fGetShieldedNotesCountResponseV0\x12\x1f\n\x11total_notes_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xce\x44\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x81\x01\n\x12getDocumentHistory\x12\x34.org.dash.platform.dapi.v0.GetDocumentHistoryRequest\x1a\x35.org.dash.platform.dapi.v0.GetDocumentHistoryResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNotesCount\x12\x37.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponseb\x06proto3' + serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xde\x15\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x12R\n\x02v1\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1H\x00\x1a\xfe\x02\n\x12\x44ocumentFieldValue\x12\x14\n\nbool_value\x18\x01 \x01(\x08H\x00\x12\x19\n\x0bint64_value\x18\x02 \x01(\x12\x42\x02\x30\x01H\x00\x12\x1a\n\x0cuint64_value\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04text\x18\x05 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x06 \x01(\x0cH\x00\x12[\n\x04list\x18\x07 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue.ValueListH\x00\x12\x14\n\nnull_value\x18\x08 \x01(\x08H\x00\x1a^\n\tValueList\x12Q\n\x06values\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueB\t\n\x07variant\x1a\xbe\x01\n\x0bWhereClause\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12N\n\x08operator\x18\x02 \x01(\x0e\x32<.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereOperator\x12P\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x1a\xa4\x01\n\x0fHavingAggregate\x12Y\n\x08\x66unction\x18\x01 \x01(\x0e\x32G.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\'\n\x08\x46unction\x12\t\n\x05\x43OUNT\x10\x00\x12\x07\n\x03SUM\x10\x01\x12\x07\n\x03\x41VG\x10\x02\x1a\xf9\x03\n\x0cHavingClause\x12Q\n\taggregate\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate\x12V\n\x08operator\x18\x02 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause.Operator\x12R\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueH\x00\"\xe0\x01\n\x08Operator\x12\t\n\x05\x45QUAL\x10\x00\x12\r\n\tNOT_EQUAL\x10\x01\x12\x10\n\x0cGREATER_THAN\x10\x02\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x03\x12\r\n\tLESS_THAN\x10\x04\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x05\x12\x0b\n\x07\x42\x45TWEEN\x10\x06\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x07\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x08\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\t\x12\x06\n\x02IN\x10\nB\x07\n\x05right\x1a\x90\x01\n\x0bOrderClause\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x12S\n\taggregate\x18\x03 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregateH\x00\x12\x11\n\tascending\x18\x02 \x01(\x08\x42\x08\n\x06target\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\x1a\xf3\x05\n\x15GetDocumentsRequestV1\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x12\\\n\x07selects\x18\t \x03(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select\x12\x10\n\x08group_by\x18\n \x03(\t\x12K\n\x06having\x18\x0b \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause\x12\x13\n\x06offset\x18\x0c \x01(\rH\x02\x88\x01\x01\x1a\xc9\x01\n\x06Select\x12\x66\n\x08\x66unction\x18\x01 \x01(\x0e\x32T.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"H\n\x08\x46unction\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x12\x07\n\x03SUM\x10\x02\x12\x07\n\x03\x41VG\x10\x03\x12\x07\n\x03MIN\x10\x04\x12\x07\n\x03MAX\x10\x05\x42\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xe7\x01\n\rWhereOperator\x12\t\n\x05\x45QUAL\x10\x00\x12\x10\n\x0cGREATER_THAN\x10\x01\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x04\x12\x0b\n\x07\x42\x45TWEEN\x10\x05\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x06\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x07\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\x08\x12\x06\n\x02IN\x10\t\x12\x0f\n\x0bSTARTS_WITH\x10\nB\t\n\x07version\"\x87\x16\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x12T\n\x02v1\x18\x02 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\x1a\x99\x12\n\x16GetDocumentsResponseV1\x12\x61\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ResultDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x1aL\n\nCountEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07_in_key\x1ar\n\x0c\x43ountEntries\x12\x62\n\x07\x65ntries\x18\x01 \x03(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntry\x1a\xa0\x01\n\x0c\x43ountResults\x12\x1d\n\x0f\x61ggregate_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x66\n\x07\x65ntries\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x42\t\n\x07variant\x1aH\n\x08SumEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x0f\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1an\n\nSumEntries\x12`\n\x07\x65ntries\x18\x01 \x03(\x0b\x32O.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntry\x1a\x9a\x01\n\nSumResults\x12\x1b\n\raggregate_sum\x18\x01 \x01(\x12\x42\x02\x30\x01H\x00\x12\x64\n\x07\x65ntries\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntriesH\x00\x42\t\n\x07variant\x1a_\n\x0c\x41verageEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x04 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1av\n\x0e\x41verageEntries\x12\x64\n\x07\x65ntries\x18\x01 \x03(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntry\x1a\x36\n\x10\x41verageAggregate\x12\x11\n\x05\x63ount\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x02 \x01(\x12\x42\x02\x30\x01\x1a\xfb\x01\n\x0e\x41verageResults\x12t\n\x11\x61ggregate_average\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageAggregateH\x00\x12h\n\x07\x65ntries\x18\x02 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntriesH\x00\x42\t\n\x07variant\x1az\n\x0bRankedEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\x13\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x11\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01H\x00\x12\r\n\x03\x61vg\x18\x04 \x01(\x01H\x00\x12\x13\n\x06in_key\x18\x05 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05valueB\t\n\x07_in_key\x1a\x9a\x01\n\rRankedEntries\x12\x63\n\x07\x65ntries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry\x12\x18\n\x07skipped\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_skipped\x1a\x9b\x04\n\nResultData\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountResultsH\x00\x12\x61\n\x04sums\x18\x03 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumResultsH\x00\x12i\n\x08\x61verages\x18\x04 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageResultsH\x00\x12\x66\n\x06ranked\x18\x05 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntriesH\x00\x42\t\n\x07variantB\x08\n\x06resultB\t\n\x07version\"\xf4\x02\n\x19GetDocumentHistoryRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0H\x00\x1a\xeb\x01\n\x1bGetDocumentHistoryRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x03 \x01(\x0c\x12+\n\x05limit\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x07 \x01(\x08\x42\t\n\x07version\"\xf7\x04\n\x1aGetDocumentHistoryResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0H\x00\x1a\xeb\x03\n\x1cGetDocumentHistoryResponseV0\x12~\n\x10\x64ocument_history\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x14\x44ocumentHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\x95\x01\n\x0f\x44ocumentHistory\x12\x81\x01\n\x10\x64ocument_entries\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xbc\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x9b\x04\n#GetShieldedEncryptedNotesResponseV0\x12\x8a\x01\n\x0f\x65ncrypted_notes\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aW\n\rEncryptedNote\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x0b\n\x03\x63mx\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65ncrypted_note\x18\x03 \x01(\x0c\x12\x0e\n\x06\x63v_net\x18\x04 \x01(\x0c\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc0\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1a/\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd3\x02\n\x1dGetShieldedNotesCountResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse.GetShieldedNotesCountResponseV0H\x00\x1a\xbe\x01\n\x1fGetShieldedNotesCountResponseV0\x12\x1f\n\x11total_notes_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xce\x44\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x81\x01\n\x12getDocumentHistory\x12\x34.org.dash.platform.dapi.v0.GetDocumentHistoryRequest\x1a\x35.org.dash.platform.dapi.v0.GetDocumentHistoryResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNotesCount\x12\x37.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponseb\x06proto3' , dependencies=[google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -62,8 +62,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=65780, - serialized_end=65870, + serialized_start=65812, + serialized_end=65902, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -340,8 +340,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=28490, - serialized_end=28563, + serialized_start=28522, + serialized_end=28595, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -370,8 +370,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=29485, - serialized_end=29564, + serialized_start=29517, + serialized_end=29596, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -400,8 +400,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=33193, - serialized_end=33254, + serialized_start=33225, + serialized_end=33286, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -425,8 +425,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=51818, - serialized_end=51856, + serialized_start=51850, + serialized_end=51888, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSREQUEST_ACTIONSTATUS) @@ -450,8 +450,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=53103, - serialized_end=53138, + serialized_start=53135, + serialized_end=53170, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT_ACTIONTYPE) @@ -475,8 +475,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=51818, - serialized_end=51856, + serialized_start=51850, + serialized_end=51888, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSIGNERSREQUEST_ACTIONSTATUS) @@ -4724,6 +4724,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='in_key', full_name='org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.in_key', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -4740,9 +4747,14 @@ index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), + _descriptor.OneofDescriptor( + name='_in_key', full_name='org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry._in_key', + index=1, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), ], serialized_start=15662, - serialized_end=15752, + serialized_end=15784, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES = _descriptor.Descriptor( @@ -4784,8 +4796,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15755, - serialized_end=15909, + serialized_start=15787, + serialized_end=15941, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RESULTDATA = _descriptor.Descriptor( @@ -4848,8 +4860,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15912, - serialized_end=16451, + serialized_start=15944, + serialized_end=16483, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1 = _descriptor.Descriptor( @@ -4899,7 +4911,7 @@ fields=[]), ], serialized_start=14164, - serialized_end=16461, + serialized_end=16493, ) _GETDOCUMENTSRESPONSE = _descriptor.Descriptor( @@ -4942,7 +4954,7 @@ fields=[]), ], serialized_start=13681, - serialized_end=16472, + serialized_end=16504, ) @@ -5015,8 +5027,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16601, - serialized_end=16836, + serialized_start=16633, + serialized_end=16868, ) _GETDOCUMENTHISTORYREQUEST = _descriptor.Descriptor( @@ -5051,8 +5063,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16475, - serialized_end=16847, + serialized_start=16507, + serialized_end=16879, ) @@ -5090,8 +5102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17253, - serialized_end=17308, + serialized_start=17285, + serialized_end=17340, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORY = _descriptor.Descriptor( @@ -5121,8 +5133,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17311, - serialized_end=17460, + serialized_start=17343, + serialized_end=17492, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 = _descriptor.Descriptor( @@ -5171,8 +5183,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16979, - serialized_end=17470, + serialized_start=17011, + serialized_end=17502, ) _GETDOCUMENTHISTORYRESPONSE = _descriptor.Descriptor( @@ -5207,8 +5219,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16850, - serialized_end=17481, + serialized_start=16882, + serialized_end=17513, ) @@ -5246,8 +5258,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17633, - serialized_end=17710, + serialized_start=17665, + serialized_end=17742, ) _GETIDENTITYBYPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -5282,8 +5294,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17484, - serialized_end=17721, + serialized_start=17516, + serialized_end=17753, ) @@ -5333,8 +5345,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17877, - serialized_end=18059, + serialized_start=17909, + serialized_end=18091, ) _GETIDENTITYBYPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -5369,8 +5381,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17724, - serialized_end=18070, + serialized_start=17756, + serialized_end=18102, ) @@ -5420,8 +5432,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18251, - serialized_end=18379, + serialized_start=18283, + serialized_end=18411, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -5456,8 +5468,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18073, - serialized_end=18390, + serialized_start=18105, + serialized_end=18422, ) @@ -5493,8 +5505,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19003, - serialized_end=19057, + serialized_start=19035, + serialized_end=19089, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0_IDENTITYPROVEDRESPONSE = _descriptor.Descriptor( @@ -5536,8 +5548,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19060, - serialized_end=19226, + serialized_start=19092, + serialized_end=19258, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0 = _descriptor.Descriptor( @@ -5586,8 +5598,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18574, - serialized_end=19236, + serialized_start=18606, + serialized_end=19268, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -5622,8 +5634,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18393, - serialized_end=19247, + serialized_start=18425, + serialized_end=19279, ) @@ -5661,8 +5673,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19405, - serialized_end=19490, + serialized_start=19437, + serialized_end=19522, ) _WAITFORSTATETRANSITIONRESULTREQUEST = _descriptor.Descriptor( @@ -5697,8 +5709,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19250, - serialized_end=19501, + serialized_start=19282, + serialized_end=19533, ) @@ -5748,8 +5760,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19663, - serialized_end=19902, + serialized_start=19695, + serialized_end=19934, ) _WAITFORSTATETRANSITIONRESULTRESPONSE = _descriptor.Descriptor( @@ -5784,8 +5796,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19504, - serialized_end=19913, + serialized_start=19536, + serialized_end=19945, ) @@ -5823,8 +5835,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20041, - serialized_end=20101, + serialized_start=20073, + serialized_end=20133, ) _GETCONSENSUSPARAMSREQUEST = _descriptor.Descriptor( @@ -5859,8 +5871,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19916, - serialized_end=20112, + serialized_start=19948, + serialized_end=20144, ) @@ -5905,8 +5917,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20243, - serialized_end=20323, + serialized_start=20275, + serialized_end=20355, ) _GETCONSENSUSPARAMSRESPONSE_CONSENSUSPARAMSEVIDENCE = _descriptor.Descriptor( @@ -5950,8 +5962,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20325, - serialized_end=20423, + serialized_start=20357, + serialized_end=20455, ) _GETCONSENSUSPARAMSRESPONSE_GETCONSENSUSPARAMSRESPONSEV0 = _descriptor.Descriptor( @@ -5988,8 +6000,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20426, - serialized_end=20644, + serialized_start=20458, + serialized_end=20676, ) _GETCONSENSUSPARAMSRESPONSE = _descriptor.Descriptor( @@ -6024,8 +6036,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20115, - serialized_end=20655, + serialized_start=20147, + serialized_end=20687, ) @@ -6056,8 +6068,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20819, - serialized_end=20875, + serialized_start=20851, + serialized_end=20907, ) _GETPROTOCOLVERSIONUPGRADESTATEREQUEST = _descriptor.Descriptor( @@ -6092,8 +6104,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20658, - serialized_end=20886, + serialized_start=20690, + serialized_end=20918, ) @@ -6124,8 +6136,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21351, - serialized_end=21501, + serialized_start=21383, + serialized_end=21533, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0_VERSIONENTRY = _descriptor.Descriptor( @@ -6162,8 +6174,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21503, - serialized_end=21561, + serialized_start=21535, + serialized_end=21593, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0 = _descriptor.Descriptor( @@ -6212,8 +6224,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21054, - serialized_end=21571, + serialized_start=21086, + serialized_end=21603, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE = _descriptor.Descriptor( @@ -6248,8 +6260,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20889, - serialized_end=21582, + serialized_start=20921, + serialized_end=21614, ) @@ -6294,8 +6306,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21762, - serialized_end=21865, + serialized_start=21794, + serialized_end=21897, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -6330,8 +6342,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21585, - serialized_end=21876, + serialized_start=21617, + serialized_end=21908, ) @@ -6362,8 +6374,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22379, - serialized_end=22554, + serialized_start=22411, + serialized_end=22586, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0_VERSIONSIGNAL = _descriptor.Descriptor( @@ -6400,8 +6412,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22556, - serialized_end=22609, + serialized_start=22588, + serialized_end=22641, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -6450,8 +6462,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22060, - serialized_end=22619, + serialized_start=22092, + serialized_end=22651, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE = _descriptor.Descriptor( @@ -6486,8 +6498,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21879, - serialized_end=22630, + serialized_start=21911, + serialized_end=22662, ) @@ -6539,8 +6551,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22743, - serialized_end=22867, + serialized_start=22775, + serialized_end=22899, ) _GETEPOCHSINFOREQUEST = _descriptor.Descriptor( @@ -6575,8 +6587,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22633, - serialized_end=22878, + serialized_start=22665, + serialized_end=22910, ) @@ -6607,8 +6619,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23239, - serialized_end=23356, + serialized_start=23271, + serialized_end=23388, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO = _descriptor.Descriptor( @@ -6673,8 +6685,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23359, - serialized_end=23525, + serialized_start=23391, + serialized_end=23557, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0 = _descriptor.Descriptor( @@ -6723,8 +6735,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22995, - serialized_end=23535, + serialized_start=23027, + serialized_end=23567, ) _GETEPOCHSINFORESPONSE = _descriptor.Descriptor( @@ -6759,8 +6771,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22881, - serialized_end=23546, + serialized_start=22913, + serialized_end=23578, ) @@ -6819,8 +6831,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23687, - serialized_end=23857, + serialized_start=23719, + serialized_end=23889, ) _GETFINALIZEDEPOCHINFOSREQUEST = _descriptor.Descriptor( @@ -6855,8 +6867,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23549, - serialized_end=23868, + serialized_start=23581, + serialized_end=23900, ) @@ -6887,8 +6899,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24294, - serialized_end=24458, + serialized_start=24326, + serialized_end=24490, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_FINALIZEDEPOCHINFO = _descriptor.Descriptor( @@ -7002,8 +7014,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24461, - serialized_end=25004, + serialized_start=24493, + serialized_end=25036, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_BLOCKPROPOSER = _descriptor.Descriptor( @@ -7040,8 +7052,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25006, - serialized_end=25063, + serialized_start=25038, + serialized_end=25095, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -7090,8 +7102,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24012, - serialized_end=25073, + serialized_start=24044, + serialized_end=25105, ) _GETFINALIZEDEPOCHINFOSRESPONSE = _descriptor.Descriptor( @@ -7126,8 +7138,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23871, - serialized_end=25084, + serialized_start=23903, + serialized_end=25116, ) @@ -7165,8 +7177,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25579, - serialized_end=25648, + serialized_start=25611, + serialized_end=25680, ) _GETCONTESTEDRESOURCESREQUEST_GETCONTESTEDRESOURCESREQUESTV0 = _descriptor.Descriptor( @@ -7262,8 +7274,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25222, - serialized_end=25682, + serialized_start=25254, + serialized_end=25714, ) _GETCONTESTEDRESOURCESREQUEST = _descriptor.Descriptor( @@ -7298,8 +7310,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25087, - serialized_end=25693, + serialized_start=25119, + serialized_end=25725, ) @@ -7330,8 +7342,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26135, - serialized_end=26195, + serialized_start=26167, + serialized_end=26227, ) _GETCONTESTEDRESOURCESRESPONSE_GETCONTESTEDRESOURCESRESPONSEV0 = _descriptor.Descriptor( @@ -7380,8 +7392,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25834, - serialized_end=26205, + serialized_start=25866, + serialized_end=26237, ) _GETCONTESTEDRESOURCESRESPONSE = _descriptor.Descriptor( @@ -7416,8 +7428,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25696, - serialized_end=26216, + serialized_start=25728, + serialized_end=26248, ) @@ -7455,8 +7467,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26729, - serialized_end=26802, + serialized_start=26761, + serialized_end=26834, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0_ENDATTIMEINFO = _descriptor.Descriptor( @@ -7493,8 +7505,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26804, - serialized_end=26871, + serialized_start=26836, + serialized_end=26903, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0 = _descriptor.Descriptor( @@ -7579,8 +7591,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26354, - serialized_end=26930, + serialized_start=26386, + serialized_end=26962, ) _GETVOTEPOLLSBYENDDATEREQUEST = _descriptor.Descriptor( @@ -7615,8 +7627,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26219, - serialized_end=26941, + serialized_start=26251, + serialized_end=26973, ) @@ -7654,8 +7666,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27390, - serialized_end=27476, + serialized_start=27422, + serialized_end=27508, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0_SERIALIZEDVOTEPOLLSBYTIMESTAMPS = _descriptor.Descriptor( @@ -7692,8 +7704,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27479, - serialized_end=27694, + serialized_start=27511, + serialized_end=27726, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0 = _descriptor.Descriptor( @@ -7742,8 +7754,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27082, - serialized_end=27704, + serialized_start=27114, + serialized_end=27736, ) _GETVOTEPOLLSBYENDDATERESPONSE = _descriptor.Descriptor( @@ -7778,8 +7790,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26944, - serialized_end=27715, + serialized_start=26976, + serialized_end=27747, ) @@ -7817,8 +7829,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28404, - serialized_end=28488, + serialized_start=28436, + serialized_end=28520, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0 = _descriptor.Descriptor( @@ -7915,8 +7927,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27877, - serialized_end=28602, + serialized_start=27909, + serialized_end=28634, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -7951,8 +7963,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27718, - serialized_end=28613, + serialized_start=27750, + serialized_end=28645, ) @@ -8024,8 +8036,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29113, - serialized_end=29587, + serialized_start=29145, + serialized_end=29619, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -8091,8 +8103,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29590, - serialized_end=30042, + serialized_start=29622, + serialized_end=30074, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -8146,8 +8158,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30044, - serialized_end=30151, + serialized_start=30076, + serialized_end=30183, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -8196,8 +8208,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28778, - serialized_end=30161, + serialized_start=28810, + serialized_end=30193, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -8232,8 +8244,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28616, - serialized_end=30172, + serialized_start=28648, + serialized_end=30204, ) @@ -8271,8 +8283,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28404, - serialized_end=28488, + serialized_start=28436, + serialized_end=28520, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUESTV0 = _descriptor.Descriptor( @@ -8368,8 +8380,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30359, - serialized_end=30889, + serialized_start=30391, + serialized_end=30921, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -8404,8 +8416,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30175, - serialized_end=30900, + serialized_start=30207, + serialized_end=30932, ) @@ -8443,8 +8455,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=31440, - serialized_end=31507, + serialized_start=31472, + serialized_end=31539, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -8493,8 +8505,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31090, - serialized_end=31517, + serialized_start=31122, + serialized_end=31549, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -8529,8 +8541,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30903, - serialized_end=31528, + serialized_start=30935, + serialized_end=31560, ) @@ -8568,8 +8580,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32077, - serialized_end=32174, + serialized_start=32109, + serialized_end=32206, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -8639,8 +8651,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31702, - serialized_end=32205, + serialized_start=31734, + serialized_end=32237, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -8675,8 +8687,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31531, - serialized_end=32216, + serialized_start=31563, + serialized_end=32248, ) @@ -8714,8 +8726,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32719, - serialized_end=32966, + serialized_start=32751, + serialized_end=32998, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -8758,8 +8770,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32969, - serialized_end=33270, + serialized_start=33001, + serialized_end=33302, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -8810,8 +8822,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33273, - serialized_end=33550, + serialized_start=33305, + serialized_end=33582, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -8860,8 +8872,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32393, - serialized_end=33560, + serialized_start=32425, + serialized_end=33592, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -8896,8 +8908,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32219, - serialized_end=33571, + serialized_start=32251, + serialized_end=33603, ) @@ -8935,8 +8947,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33735, - serialized_end=33803, + serialized_start=33767, + serialized_end=33835, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -8971,8 +8983,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33574, - serialized_end=33814, + serialized_start=33606, + serialized_end=33846, ) @@ -9022,8 +9034,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33982, - serialized_end=34171, + serialized_start=34014, + serialized_end=34203, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -9058,8 +9070,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33817, - serialized_end=34182, + serialized_start=33849, + serialized_end=34214, ) @@ -9090,8 +9102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34331, - serialized_end=34382, + serialized_start=34363, + serialized_end=34414, ) _GETTOTALCREDITSINPLATFORMREQUEST = _descriptor.Descriptor( @@ -9126,8 +9138,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34185, - serialized_end=34393, + serialized_start=34217, + serialized_end=34425, ) @@ -9177,8 +9189,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34546, - serialized_end=34730, + serialized_start=34578, + serialized_end=34762, ) _GETTOTALCREDITSINPLATFORMRESPONSE = _descriptor.Descriptor( @@ -9213,8 +9225,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34396, - serialized_end=34741, + serialized_start=34428, + serialized_end=34773, ) @@ -9259,8 +9271,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34860, - serialized_end=34929, + serialized_start=34892, + serialized_end=34961, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -9295,8 +9307,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34744, - serialized_end=34940, + serialized_start=34776, + serialized_end=34972, ) @@ -9327,8 +9339,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35313, - serialized_end=35341, + serialized_start=35345, + serialized_end=35373, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -9377,8 +9389,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35063, - serialized_end=35351, + serialized_start=35095, + serialized_end=35383, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -9413,8 +9425,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34943, - serialized_end=35362, + serialized_start=34975, + serialized_end=35394, ) @@ -9438,8 +9450,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35463, - serialized_end=35483, + serialized_start=35495, + serialized_end=35515, ) _GETSTATUSREQUEST = _descriptor.Descriptor( @@ -9474,8 +9486,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35365, - serialized_end=35494, + serialized_start=35397, + serialized_end=35526, ) @@ -9530,8 +9542,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36371, - serialized_end=36465, + serialized_start=36403, + serialized_end=36497, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_TENDERDASH = _descriptor.Descriptor( @@ -9568,8 +9580,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36698, - serialized_end=36738, + serialized_start=36730, + serialized_end=36770, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_DRIVE = _descriptor.Descriptor( @@ -9613,8 +9625,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36740, - serialized_end=36800, + serialized_start=36772, + serialized_end=36832, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL = _descriptor.Descriptor( @@ -9651,8 +9663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36468, - serialized_end=36800, + serialized_start=36500, + serialized_end=36832, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION = _descriptor.Descriptor( @@ -9689,8 +9701,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36158, - serialized_end=36800, + serialized_start=36190, + serialized_end=36832, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_TIME = _descriptor.Descriptor( @@ -9756,8 +9768,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36802, - serialized_end=36929, + serialized_start=36834, + serialized_end=36961, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NODE = _descriptor.Descriptor( @@ -9799,8 +9811,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36931, - serialized_end=36991, + serialized_start=36963, + serialized_end=37023, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_CHAIN = _descriptor.Descriptor( @@ -9891,8 +9903,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36994, - serialized_end=37301, + serialized_start=37026, + serialized_end=37333, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NETWORK = _descriptor.Descriptor( @@ -9936,8 +9948,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37303, - serialized_end=37370, + serialized_start=37335, + serialized_end=37402, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_STATESYNC = _descriptor.Descriptor( @@ -10016,8 +10028,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37373, - serialized_end=37634, + serialized_start=37405, + serialized_end=37666, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -10082,8 +10094,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35599, - serialized_end=37634, + serialized_start=35631, + serialized_end=37666, ) _GETSTATUSRESPONSE = _descriptor.Descriptor( @@ -10118,8 +10130,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35497, - serialized_end=37645, + serialized_start=35529, + serialized_end=37677, ) @@ -10143,8 +10155,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37782, - serialized_end=37814, + serialized_start=37814, + serialized_end=37846, ) _GETCURRENTQUORUMSINFOREQUEST = _descriptor.Descriptor( @@ -10179,8 +10191,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37648, - serialized_end=37825, + serialized_start=37680, + serialized_end=37857, ) @@ -10225,8 +10237,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37965, - serialized_end=38035, + serialized_start=37997, + serialized_end=38067, ) _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 = _descriptor.Descriptor( @@ -10277,8 +10289,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38038, - serialized_end=38213, + serialized_start=38070, + serialized_end=38245, ) _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 = _descriptor.Descriptor( @@ -10336,8 +10348,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38216, - serialized_end=38490, + serialized_start=38248, + serialized_end=38522, ) _GETCURRENTQUORUMSINFORESPONSE = _descriptor.Descriptor( @@ -10372,8 +10384,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37828, - serialized_end=38501, + serialized_start=37860, + serialized_end=38533, ) @@ -10418,8 +10430,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38647, - serialized_end=38737, + serialized_start=38679, + serialized_end=38769, ) _GETIDENTITYTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -10454,8 +10466,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38504, - serialized_end=38748, + serialized_start=38536, + serialized_end=38780, ) @@ -10498,8 +10510,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39187, - serialized_end=39258, + serialized_start=39219, + serialized_end=39290, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0_TOKENBALANCES = _descriptor.Descriptor( @@ -10529,8 +10541,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39261, - serialized_end=39415, + serialized_start=39293, + serialized_end=39447, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -10579,8 +10591,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38898, - serialized_end=39425, + serialized_start=38930, + serialized_end=39457, ) _GETIDENTITYTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -10615,8 +10627,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38751, - serialized_end=39436, + serialized_start=38783, + serialized_end=39468, ) @@ -10661,8 +10673,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39588, - serialized_end=39680, + serialized_start=39620, + serialized_end=39712, ) _GETIDENTITIESTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -10697,8 +10709,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39439, - serialized_end=39691, + serialized_start=39471, + serialized_end=39723, ) @@ -10741,8 +10753,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40159, - serialized_end=40241, + serialized_start=40191, + serialized_end=40273, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0_IDENTITYTOKENBALANCES = _descriptor.Descriptor( @@ -10772,8 +10784,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40244, - serialized_end=40427, + serialized_start=40276, + serialized_end=40459, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -10822,8 +10834,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39847, - serialized_end=40437, + serialized_start=39879, + serialized_end=40469, ) _GETIDENTITIESTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -10858,8 +10870,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39694, - serialized_end=40448, + serialized_start=39726, + serialized_end=40480, ) @@ -10904,8 +10916,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40585, - serialized_end=40672, + serialized_start=40617, + serialized_end=40704, ) _GETIDENTITYTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -10940,8 +10952,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40451, - serialized_end=40683, + serialized_start=40483, + serialized_end=40715, ) @@ -10972,8 +10984,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41097, - serialized_end=41137, + serialized_start=41129, + serialized_end=41169, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -11015,8 +11027,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41140, - serialized_end=41316, + serialized_start=41172, + serialized_end=41348, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOS = _descriptor.Descriptor( @@ -11046,8 +11058,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41319, - serialized_end=41457, + serialized_start=41351, + serialized_end=41489, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -11096,8 +11108,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40824, - serialized_end=41467, + serialized_start=40856, + serialized_end=41499, ) _GETIDENTITYTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -11132,8 +11144,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40686, - serialized_end=41478, + serialized_start=40718, + serialized_end=41510, ) @@ -11178,8 +11190,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41621, - serialized_end=41710, + serialized_start=41653, + serialized_end=41742, ) _GETIDENTITIESTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -11214,8 +11226,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41481, - serialized_end=41721, + serialized_start=41513, + serialized_end=41753, ) @@ -11246,8 +11258,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41097, - serialized_end=41137, + serialized_start=41129, + serialized_end=41169, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -11289,8 +11301,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42208, - serialized_end=42391, + serialized_start=42240, + serialized_end=42423, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_IDENTITYTOKENINFOS = _descriptor.Descriptor( @@ -11320,8 +11332,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42394, - serialized_end=42545, + serialized_start=42426, + serialized_end=42577, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -11370,8 +11382,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41868, - serialized_end=42555, + serialized_start=41900, + serialized_end=42587, ) _GETIDENTITIESTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -11406,8 +11418,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41724, - serialized_end=42566, + serialized_start=41756, + serialized_end=42598, ) @@ -11445,8 +11457,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42688, - serialized_end=42749, + serialized_start=42720, + serialized_end=42781, ) _GETTOKENSTATUSESREQUEST = _descriptor.Descriptor( @@ -11481,8 +11493,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42569, - serialized_end=42760, + serialized_start=42601, + serialized_end=42792, ) @@ -11525,8 +11537,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43150, - serialized_end=43218, + serialized_start=43182, + serialized_end=43250, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0_TOKENSTATUSES = _descriptor.Descriptor( @@ -11556,8 +11568,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=43221, - serialized_end=43357, + serialized_start=43253, + serialized_end=43389, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0 = _descriptor.Descriptor( @@ -11606,8 +11618,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42886, - serialized_end=43367, + serialized_start=42918, + serialized_end=43399, ) _GETTOKENSTATUSESRESPONSE = _descriptor.Descriptor( @@ -11642,8 +11654,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42763, - serialized_end=43378, + serialized_start=42795, + serialized_end=43410, ) @@ -11681,8 +11693,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=43536, - serialized_end=43609, + serialized_start=43568, + serialized_end=43641, ) _GETTOKENDIRECTPURCHASEPRICESREQUEST = _descriptor.Descriptor( @@ -11717,8 +11729,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43381, - serialized_end=43620, + serialized_start=43413, + serialized_end=43652, ) @@ -11756,8 +11768,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44110, - serialized_end=44161, + serialized_start=44142, + serialized_end=44193, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -11787,8 +11799,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44164, - serialized_end=44331, + serialized_start=44196, + serialized_end=44363, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICEENTRY = _descriptor.Descriptor( @@ -11837,8 +11849,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44334, - serialized_end=44562, + serialized_start=44366, + serialized_end=44594, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICES = _descriptor.Descriptor( @@ -11868,8 +11880,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44565, - serialized_end=44765, + serialized_start=44597, + serialized_end=44797, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0 = _descriptor.Descriptor( @@ -11918,8 +11930,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43782, - serialized_end=44775, + serialized_start=43814, + serialized_end=44807, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE = _descriptor.Descriptor( @@ -11954,8 +11966,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43623, - serialized_end=44786, + serialized_start=43655, + serialized_end=44818, ) @@ -11993,8 +12005,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44920, - serialized_end=44984, + serialized_start=44952, + serialized_end=45016, ) _GETTOKENCONTRACTINFOREQUEST = _descriptor.Descriptor( @@ -12029,8 +12041,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44789, - serialized_end=44995, + serialized_start=44821, + serialized_end=45027, ) @@ -12068,8 +12080,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45407, - serialized_end=45484, + serialized_start=45439, + serialized_end=45516, ) _GETTOKENCONTRACTINFORESPONSE_GETTOKENCONTRACTINFORESPONSEV0 = _descriptor.Descriptor( @@ -12118,8 +12130,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45133, - serialized_end=45494, + serialized_start=45165, + serialized_end=45526, ) _GETTOKENCONTRACTINFORESPONSE = _descriptor.Descriptor( @@ -12154,8 +12166,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44998, - serialized_end=45505, + serialized_start=45030, + serialized_end=45537, ) @@ -12210,8 +12222,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45938, - serialized_end=46092, + serialized_start=45970, + serialized_end=46124, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST_GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUESTV0 = _descriptor.Descriptor( @@ -12272,8 +12284,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45682, - serialized_end=46120, + serialized_start=45714, + serialized_end=46152, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST = _descriptor.Descriptor( @@ -12308,8 +12320,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45508, - serialized_end=46131, + serialized_start=45540, + serialized_end=46163, ) @@ -12347,8 +12359,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46642, - serialized_end=46704, + serialized_start=46674, + serialized_end=46736, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENTIMEDDISTRIBUTIONENTRY = _descriptor.Descriptor( @@ -12385,8 +12397,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46707, - serialized_end=46919, + serialized_start=46739, + serialized_end=46951, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENDISTRIBUTIONS = _descriptor.Descriptor( @@ -12416,8 +12428,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46922, - serialized_end=47117, + serialized_start=46954, + serialized_end=47149, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -12466,8 +12478,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46312, - serialized_end=47127, + serialized_start=46344, + serialized_end=47159, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE = _descriptor.Descriptor( @@ -12502,8 +12514,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46134, - serialized_end=47138, + serialized_start=46166, + serialized_end=47170, ) @@ -12541,8 +12553,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47327, - serialized_end=47400, + serialized_start=47359, + serialized_end=47432, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUESTV0 = _descriptor.Descriptor( @@ -12598,8 +12610,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47403, - serialized_end=47644, + serialized_start=47435, + serialized_end=47676, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST = _descriptor.Descriptor( @@ -12634,8 +12646,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47141, - serialized_end=47655, + serialized_start=47173, + serialized_end=47687, ) @@ -12692,8 +12704,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48176, - serialized_end=48296, + serialized_start=48208, + serialized_end=48328, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSEV0 = _descriptor.Descriptor( @@ -12742,8 +12754,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47848, - serialized_end=48306, + serialized_start=47880, + serialized_end=48338, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE = _descriptor.Descriptor( @@ -12778,8 +12790,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47658, - serialized_end=48317, + serialized_start=47690, + serialized_end=48349, ) @@ -12817,8 +12829,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48448, - serialized_end=48511, + serialized_start=48480, + serialized_end=48543, ) _GETTOKENTOTALSUPPLYREQUEST = _descriptor.Descriptor( @@ -12853,8 +12865,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48320, - serialized_end=48522, + serialized_start=48352, + serialized_end=48554, ) @@ -12899,8 +12911,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48943, - serialized_end=49063, + serialized_start=48975, + serialized_end=49095, ) _GETTOKENTOTALSUPPLYRESPONSE_GETTOKENTOTALSUPPLYRESPONSEV0 = _descriptor.Descriptor( @@ -12949,8 +12961,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48657, - serialized_end=49073, + serialized_start=48689, + serialized_end=49105, ) _GETTOKENTOTALSUPPLYRESPONSE = _descriptor.Descriptor( @@ -12985,8 +12997,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48525, - serialized_end=49084, + serialized_start=48557, + serialized_end=49116, ) @@ -13031,8 +13043,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49194, - serialized_end=49286, + serialized_start=49226, + serialized_end=49318, ) _GETGROUPINFOREQUEST = _descriptor.Descriptor( @@ -13067,8 +13079,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49087, - serialized_end=49297, + serialized_start=49119, + serialized_end=49329, ) @@ -13106,8 +13118,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49655, - serialized_end=49707, + serialized_start=49687, + serialized_end=49739, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFOENTRY = _descriptor.Descriptor( @@ -13144,8 +13156,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49710, - serialized_end=49862, + serialized_start=49742, + serialized_end=49894, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFO = _descriptor.Descriptor( @@ -13180,8 +13192,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49865, - serialized_end=50003, + serialized_start=49897, + serialized_end=50035, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0 = _descriptor.Descriptor( @@ -13230,8 +13242,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49411, - serialized_end=50013, + serialized_start=49443, + serialized_end=50045, ) _GETGROUPINFORESPONSE = _descriptor.Descriptor( @@ -13266,8 +13278,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49300, - serialized_end=50024, + serialized_start=49332, + serialized_end=50056, ) @@ -13305,8 +13317,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50137, - serialized_end=50254, + serialized_start=50169, + serialized_end=50286, ) _GETGROUPINFOSREQUEST_GETGROUPINFOSREQUESTV0 = _descriptor.Descriptor( @@ -13367,8 +13379,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50257, - serialized_end=50509, + serialized_start=50289, + serialized_end=50541, ) _GETGROUPINFOSREQUEST = _descriptor.Descriptor( @@ -13403,8 +13415,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50027, - serialized_end=50520, + serialized_start=50059, + serialized_end=50552, ) @@ -13442,8 +13454,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49655, - serialized_end=49707, + serialized_start=49687, + serialized_end=49739, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPPOSITIONINFOENTRY = _descriptor.Descriptor( @@ -13487,8 +13499,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50941, - serialized_end=51136, + serialized_start=50973, + serialized_end=51168, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPINFOS = _descriptor.Descriptor( @@ -13518,8 +13530,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51139, - serialized_end=51269, + serialized_start=51171, + serialized_end=51301, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -13568,8 +13580,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50637, - serialized_end=51279, + serialized_start=50669, + serialized_end=51311, ) _GETGROUPINFOSRESPONSE = _descriptor.Descriptor( @@ -13604,8 +13616,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50523, - serialized_end=51290, + serialized_start=50555, + serialized_end=51322, ) @@ -13643,8 +13655,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51409, - serialized_end=51485, + serialized_start=51441, + serialized_end=51517, ) _GETGROUPACTIONSREQUEST_GETGROUPACTIONSREQUESTV0 = _descriptor.Descriptor( @@ -13719,8 +13731,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51488, - serialized_end=51816, + serialized_start=51520, + serialized_end=51848, ) _GETGROUPACTIONSREQUEST = _descriptor.Descriptor( @@ -13756,8 +13768,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51293, - serialized_end=51867, + serialized_start=51325, + serialized_end=51899, ) @@ -13807,8 +13819,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52249, - serialized_end=52340, + serialized_start=52281, + serialized_end=52372, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_BURNEVENT = _descriptor.Descriptor( @@ -13857,8 +13869,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52342, - serialized_end=52433, + serialized_start=52374, + serialized_end=52465, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_FREEZEEVENT = _descriptor.Descriptor( @@ -13900,8 +13912,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52435, - serialized_end=52509, + serialized_start=52467, + serialized_end=52541, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UNFREEZEEVENT = _descriptor.Descriptor( @@ -13943,8 +13955,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52511, - serialized_end=52587, + serialized_start=52543, + serialized_end=52619, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DESTROYFROZENFUNDSEVENT = _descriptor.Descriptor( @@ -13993,8 +14005,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52589, - serialized_end=52691, + serialized_start=52621, + serialized_end=52723, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_SHAREDENCRYPTEDNOTE = _descriptor.Descriptor( @@ -14038,8 +14050,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52693, - serialized_end=52793, + serialized_start=52725, + serialized_end=52825, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_PERSONALENCRYPTEDNOTE = _descriptor.Descriptor( @@ -14083,8 +14095,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52795, - serialized_end=52918, + serialized_start=52827, + serialized_end=52950, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT = _descriptor.Descriptor( @@ -14127,8 +14139,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52921, - serialized_end=53154, + serialized_start=52953, + serialized_end=53186, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENCONFIGUPDATEEVENT = _descriptor.Descriptor( @@ -14170,8 +14182,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53156, - serialized_end=53256, + serialized_start=53188, + serialized_end=53288, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICEFORQUANTITY = _descriptor.Descriptor( @@ -14208,8 +14220,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44110, - serialized_end=44161, + serialized_start=44142, + serialized_end=44193, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -14239,8 +14251,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53548, - serialized_end=53720, + serialized_start=53580, + serialized_end=53752, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT = _descriptor.Descriptor( @@ -14294,8 +14306,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53259, - serialized_end=53745, + serialized_start=53291, + serialized_end=53777, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONEVENT = _descriptor.Descriptor( @@ -14344,8 +14356,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53748, - serialized_end=54128, + serialized_start=53780, + serialized_end=54160, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTEVENT = _descriptor.Descriptor( @@ -14380,8 +14392,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54131, - serialized_end=54270, + serialized_start=54163, + serialized_end=54302, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTCREATEEVENT = _descriptor.Descriptor( @@ -14411,8 +14423,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54272, - serialized_end=54319, + serialized_start=54304, + serialized_end=54351, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTUPDATEEVENT = _descriptor.Descriptor( @@ -14442,8 +14454,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54321, - serialized_end=54368, + serialized_start=54353, + serialized_end=54400, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTEVENT = _descriptor.Descriptor( @@ -14478,8 +14490,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54371, - serialized_end=54510, + serialized_start=54403, + serialized_end=54542, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENEVENT = _descriptor.Descriptor( @@ -14563,8 +14575,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54513, - serialized_end=55490, + serialized_start=54545, + serialized_end=55522, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONENTRY = _descriptor.Descriptor( @@ -14601,8 +14613,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55493, - serialized_end=55640, + serialized_start=55525, + serialized_end=55672, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONS = _descriptor.Descriptor( @@ -14632,8 +14644,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55643, - serialized_end=55775, + serialized_start=55675, + serialized_end=55807, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -14682,8 +14694,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51990, - serialized_end=55785, + serialized_start=52022, + serialized_end=55817, ) _GETGROUPACTIONSRESPONSE = _descriptor.Descriptor( @@ -14718,8 +14730,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51870, - serialized_end=55796, + serialized_start=51902, + serialized_end=55828, ) @@ -14778,8 +14790,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55934, - serialized_end=56140, + serialized_start=55966, + serialized_end=56172, ) _GETGROUPACTIONSIGNERSREQUEST = _descriptor.Descriptor( @@ -14815,8 +14827,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55799, - serialized_end=56191, + serialized_start=55831, + serialized_end=56223, ) @@ -14854,8 +14866,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56623, - serialized_end=56676, + serialized_start=56655, + serialized_end=56708, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0_GROUPACTIONSIGNERS = _descriptor.Descriptor( @@ -14885,8 +14897,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56679, - serialized_end=56824, + serialized_start=56711, + serialized_end=56856, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0 = _descriptor.Descriptor( @@ -14935,8 +14947,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56332, - serialized_end=56834, + serialized_start=56364, + serialized_end=56866, ) _GETGROUPACTIONSIGNERSRESPONSE = _descriptor.Descriptor( @@ -14971,8 +14983,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56194, - serialized_end=56845, + serialized_start=56226, + serialized_end=56877, ) @@ -15010,8 +15022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56961, - serialized_end=57018, + serialized_start=56993, + serialized_end=57050, ) _GETADDRESSINFOREQUEST = _descriptor.Descriptor( @@ -15046,8 +15058,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56848, - serialized_end=57029, + serialized_start=56880, + serialized_end=57061, ) @@ -15090,8 +15102,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57032, - serialized_end=57165, + serialized_start=57064, + serialized_end=57197, ) @@ -15129,8 +15141,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57167, - serialized_end=57216, + serialized_start=57199, + serialized_end=57248, ) @@ -15161,8 +15173,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57218, - serialized_end=57313, + serialized_start=57250, + serialized_end=57345, ) @@ -15212,8 +15224,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57315, - serialized_end=57424, + serialized_start=57347, + serialized_end=57456, ) @@ -15251,8 +15263,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57426, - serialized_end=57546, + serialized_start=57458, + serialized_end=57578, ) @@ -15283,8 +15295,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57548, - serialized_end=57655, + serialized_start=57580, + serialized_end=57687, ) @@ -15334,8 +15346,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57775, - serialized_end=58000, + serialized_start=57807, + serialized_end=58032, ) _GETADDRESSINFORESPONSE = _descriptor.Descriptor( @@ -15370,8 +15382,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57658, - serialized_end=58011, + serialized_start=57690, + serialized_end=58043, ) @@ -15409,8 +15421,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58136, - serialized_end=58198, + serialized_start=58168, + serialized_end=58230, ) _GETADDRESSESINFOSREQUEST = _descriptor.Descriptor( @@ -15445,8 +15457,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58014, - serialized_end=58209, + serialized_start=58046, + serialized_end=58241, ) @@ -15496,8 +15508,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58338, - serialized_end=58570, + serialized_start=58370, + serialized_end=58602, ) _GETADDRESSESINFOSRESPONSE = _descriptor.Descriptor( @@ -15532,8 +15544,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58212, - serialized_end=58581, + serialized_start=58244, + serialized_end=58613, ) @@ -15557,8 +15569,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58721, - serialized_end=58754, + serialized_start=58753, + serialized_end=58786, ) _GETADDRESSESTRUNKSTATEREQUEST = _descriptor.Descriptor( @@ -15593,8 +15605,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58584, - serialized_end=58765, + serialized_start=58616, + serialized_end=58797, ) @@ -15632,8 +15644,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58909, - serialized_end=59055, + serialized_start=58941, + serialized_end=59087, ) _GETADDRESSESTRUNKSTATERESPONSE = _descriptor.Descriptor( @@ -15668,8 +15680,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58768, - serialized_end=59066, + serialized_start=58800, + serialized_end=59098, ) @@ -15714,8 +15726,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59209, - serialized_end=59298, + serialized_start=59241, + serialized_end=59330, ) _GETADDRESSESBRANCHSTATEREQUEST = _descriptor.Descriptor( @@ -15750,8 +15762,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59069, - serialized_end=59309, + serialized_start=59101, + serialized_end=59341, ) @@ -15782,8 +15794,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59455, - serialized_end=59510, + serialized_start=59487, + serialized_end=59542, ) _GETADDRESSESBRANCHSTATERESPONSE = _descriptor.Descriptor( @@ -15818,8 +15830,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59312, - serialized_end=59521, + serialized_start=59344, + serialized_end=59553, ) @@ -15864,8 +15876,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59685, - serialized_end=59799, + serialized_start=59717, + serialized_end=59831, ) _GETRECENTADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -15900,8 +15912,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59524, - serialized_end=59810, + serialized_start=59556, + serialized_end=59842, ) @@ -15951,8 +15963,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59978, - serialized_end=60242, + serialized_start=60010, + serialized_end=60274, ) _GETRECENTADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -15987,8 +15999,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59813, - serialized_end=60253, + serialized_start=59845, + serialized_end=60285, ) @@ -16026,8 +16038,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60255, - serialized_end=60326, + serialized_start=60287, + serialized_end=60358, ) @@ -16077,8 +16089,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60329, - serialized_end=60505, + serialized_start=60361, + serialized_end=60537, ) @@ -16109,8 +16121,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60507, - serialized_end=60599, + serialized_start=60539, + serialized_end=60631, ) @@ -16155,8 +16167,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60602, - serialized_end=60776, + serialized_start=60634, + serialized_end=60808, ) @@ -16187,8 +16199,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60779, - serialized_end=60914, + serialized_start=60811, + serialized_end=60946, ) @@ -16226,8 +16238,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61106, - serialized_end=61203, + serialized_start=61138, + serialized_end=61235, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -16262,8 +16274,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60917, - serialized_end=61214, + serialized_start=60949, + serialized_end=61246, ) @@ -16313,8 +16325,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61410, - serialized_end=61702, + serialized_start=61442, + serialized_end=61734, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -16349,8 +16361,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61217, - serialized_end=61713, + serialized_start=61249, + serialized_end=61745, ) @@ -16395,8 +16407,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61862, - serialized_end=61949, + serialized_start=61894, + serialized_end=61981, ) _GETSHIELDEDENCRYPTEDNOTESREQUEST = _descriptor.Descriptor( @@ -16431,8 +16443,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61716, - serialized_end=61960, + serialized_start=61748, + serialized_end=61992, ) @@ -16484,8 +16496,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62407, - serialized_end=62494, + serialized_start=62439, + serialized_end=62526, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0_ENCRYPTEDNOTES = _descriptor.Descriptor( @@ -16515,8 +16527,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62497, - serialized_end=62642, + serialized_start=62529, + serialized_end=62674, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0 = _descriptor.Descriptor( @@ -16565,8 +16577,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62113, - serialized_end=62652, + serialized_start=62145, + serialized_end=62684, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE = _descriptor.Descriptor( @@ -16601,8 +16613,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61963, - serialized_end=62663, + serialized_start=61995, + serialized_end=62695, ) @@ -16633,8 +16645,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62791, - serialized_end=62835, + serialized_start=62823, + serialized_end=62867, ) _GETSHIELDEDANCHORSREQUEST = _descriptor.Descriptor( @@ -16669,8 +16681,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62666, - serialized_end=62846, + serialized_start=62698, + serialized_end=62878, ) @@ -16701,8 +16713,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63235, - serialized_end=63261, + serialized_start=63267, + serialized_end=63293, ) _GETSHIELDEDANCHORSRESPONSE_GETSHIELDEDANCHORSRESPONSEV0 = _descriptor.Descriptor( @@ -16751,8 +16763,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62978, - serialized_end=63271, + serialized_start=63010, + serialized_end=63303, ) _GETSHIELDEDANCHORSRESPONSE = _descriptor.Descriptor( @@ -16787,8 +16799,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62849, - serialized_end=63282, + serialized_start=62881, + serialized_end=63314, ) @@ -16819,8 +16831,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63437, - serialized_end=63490, + serialized_start=63469, + serialized_end=63522, ) _GETMOSTRECENTSHIELDEDANCHORREQUEST = _descriptor.Descriptor( @@ -16855,8 +16867,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63285, - serialized_end=63501, + serialized_start=63317, + serialized_end=63533, ) @@ -16906,8 +16918,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63660, - serialized_end=63841, + serialized_start=63692, + serialized_end=63873, ) _GETMOSTRECENTSHIELDEDANCHORRESPONSE = _descriptor.Descriptor( @@ -16942,8 +16954,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63504, - serialized_end=63852, + serialized_start=63536, + serialized_end=63884, ) @@ -16974,8 +16986,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63986, - serialized_end=64032, + serialized_start=64018, + serialized_end=64064, ) _GETSHIELDEDPOOLSTATEREQUEST = _descriptor.Descriptor( @@ -17010,8 +17022,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63855, - serialized_end=64043, + serialized_start=63887, + serialized_end=64075, ) @@ -17061,8 +17073,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64181, - serialized_end=64366, + serialized_start=64213, + serialized_end=64398, ) _GETSHIELDEDPOOLSTATERESPONSE = _descriptor.Descriptor( @@ -17097,8 +17109,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64046, - serialized_end=64377, + serialized_start=64078, + serialized_end=64409, ) @@ -17129,8 +17141,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=64514, - serialized_end=64561, + serialized_start=64546, + serialized_end=64593, ) _GETSHIELDEDNOTESCOUNTREQUEST = _descriptor.Descriptor( @@ -17165,8 +17177,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64380, - serialized_end=64572, + serialized_start=64412, + serialized_end=64604, ) @@ -17216,8 +17228,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64713, - serialized_end=64903, + serialized_start=64745, + serialized_end=64935, ) _GETSHIELDEDNOTESCOUNTRESPONSE = _descriptor.Descriptor( @@ -17252,8 +17264,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64575, - serialized_end=64914, + serialized_start=64607, + serialized_end=64946, ) @@ -17291,8 +17303,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65051, - serialized_end=65118, + serialized_start=65083, + serialized_end=65150, ) _GETSHIELDEDNULLIFIERSREQUEST = _descriptor.Descriptor( @@ -17327,8 +17339,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64917, - serialized_end=65129, + serialized_start=64949, + serialized_end=65161, ) @@ -17366,8 +17378,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65558, - serialized_end=65612, + serialized_start=65590, + serialized_end=65644, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0_NULLIFIERSTATUSES = _descriptor.Descriptor( @@ -17397,8 +17409,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65615, - serialized_end=65757, + serialized_start=65647, + serialized_end=65789, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0 = _descriptor.Descriptor( @@ -17447,8 +17459,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65270, - serialized_end=65767, + serialized_start=65302, + serialized_end=65799, ) _GETSHIELDEDNULLIFIERSRESPONSE = _descriptor.Descriptor( @@ -17483,8 +17495,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65132, - serialized_end=65778, + serialized_start=65164, + serialized_end=65810, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -17934,6 +17946,9 @@ _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.oneofs_by_name['value'].fields.append( _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.fields_by_name['avg']) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.fields_by_name['avg'].containing_oneof = _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.oneofs_by_name['value'] +_GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.oneofs_by_name['_in_key'].fields.append( + _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.fields_by_name['in_key']) +_GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.fields_by_name['in_key'].containing_oneof = _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.oneofs_by_name['_in_key'] _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES.fields_by_name['entries'].message_type = _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES.containing_type = _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1 _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES.oneofs_by_name['_skipped'].fields.append( @@ -22475,8 +22490,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=65873, - serialized_end=74655, + serialized_start=65905, + serialized_end=74687, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts index c394bd38fe9..0921efbd9f0 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts @@ -3223,6 +3223,13 @@ export namespace GetDocumentsResponse { getAvg(): number; setAvg(value: number): void; + hasInKey(): boolean; + clearInKey(): void; + getInKey(): Uint8Array | string; + getInKey_asU8(): Uint8Array; + getInKey_asB64(): string; + setInKey(value: Uint8Array | string): void; + getValueCase(): RankedEntry.ValueCase; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): RankedEntry.AsObject; @@ -3240,6 +3247,7 @@ export namespace GetDocumentsResponse { count: string, sum: string, avg: number, + inKey: Uint8Array | string, } export enum ValueCase { diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js index 10f2641e792..6bb7e0ddfde 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -30659,7 +30659,8 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank key: msg.getKey_asB64(), count: jspb.Message.getFieldWithDefault(msg, 2, "0"), sum: jspb.Message.getFieldWithDefault(msg, 3, "0"), - avg: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0) + avg: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), + inKey: msg.getInKey_asB64() }; if (includeInstance) { @@ -30712,6 +30713,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank var value = /** @type {number} */ (reader.readDouble()); msg.setAvg(value); break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setInKey(value); + break; default: reader.skipField(); break; @@ -30769,6 +30774,13 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank f ); } + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 5)); + if (f != null) { + writer.writeBytes( + 5, + f + ); + } }; @@ -30922,6 +30934,66 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.Rank }; +/** + * optional bytes in_key = 5; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes in_key = 5; + * This is a type-conversion wrapper around `getInKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getInKey())); +}; + + +/** + * optional bytes in_key = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getInKey()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.getInKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getInKey())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.setInKey = function(value) { + return jspb.Message.setField(this, 5, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.clearInKey = function() { + return jspb.Message.setField(this, 5, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry.prototype.hasInKey = function() { + return jspb.Message.getField(this, 5) != null; +}; + + /** * List of repeated fields within this message type. diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index 937962817c3..c3bfe87aba5 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -893,11 +893,11 @@ message GetDocumentsRequest { // - a is the In field AND b is the range field, in that order → existing compound distinct shape; entries carry both `in_key` (= a's value) and `key` (= b's value). // // `select=, group_by=[p], order_by=[]` (protocol v14+) — **ranked mode**: - // - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned with an `EQUAL` where clause (one per property, `group_by` names the trailing property), selecting which prefix's ranking is read. + // - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned (one clause per property, `group_by` names the trailing property) — `EQUAL` pins one prefix, and **at most one** clause may be `IN` (2..=10 distinct elements, `null` legal), fanning the walk out across one prefix branch per element and merging by `(aggregate, encoded prefix, group key)`; merged entries carry `in_key`. `offset` is rejected together with `IN` (rank-skip is per-secondary). // - `DESC` is the "top n" reading (walk the axis from the largest aggregate down), `ASC` the "bottom n" reading. Worked example: `SELECT AVG(grade) GROUP BY restaurantId ORDER BY grade DESC LIMIT 1 OFFSET 4` is the 5th-best restaurant. // // `select=, group_by=[p], having=[ ]` (protocol v14+) — **having-range mode**: - // - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one `EQUAL` pin per leading index property on a compound ranked index. + // - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one pin per leading index property on a compound ranked index, at most one of them an `IN` (2..=10 distinct elements) that fans the bound out across prefix branches and merges, entries carrying `in_key`. // - no offset or cursor pagination: a page cut at `limit` continues only by tightening the bound past the last *distinct* aggregate value seen; a cut inside a tie (several groups sharing the boundary aggregate) cannot be continued, so size `limit` above the widest expected tie. // // **Rejected shapes** (return `Unsupported`): @@ -1390,6 +1390,14 @@ message GetDocumentsResponse { // than hardcoding the literal. double avg = 4; } + // The prefix branch this entry came from, set **only** on an + // `IN`-pinned request (see the supported-shape table): the + // encoded index-key bytes of the `IN` property's pinned value — + // empty bytes for the `null` (absent-value) branch. Absent on + // single-prefix responses. The same group key can legally appear + // under two prefixes, so `(in_key, key)` is the entry's identity + // on a merged page, exactly as on `CountEntry`. + optional bytes in_key = 5; } // Ranked result entries. **Entry order IS the ranking order** — diff --git a/packages/rs-drive-abci/src/query/document_query/v1/dispatch/mod.rs b/packages/rs-drive-abci/src/query/document_query/v1/dispatch/mod.rs index 4c2d0315f48..92b1d09ed93 100644 --- a/packages/rs-drive-abci/src/query/document_query/v1/dispatch/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/v1/dispatch/mod.rs @@ -34,6 +34,10 @@ use drive::query::{RankedEntry as DriveRankedEntry, RankedEntryValue}; /// silent about). fn into_v1_ranked_entry(e: DriveRankedEntry) -> RankedEntry { RankedEntry { + // Set exactly when the request carried an `IN` prefix pin — + // drive's merge tags entries with their branch, single-branch + // responses stay untagged. + in_key: e.in_key, key: e.key, value: Some(match e.value { RankedEntryValue::Count(count) => ranked_entry::Value::Count(count), diff --git a/packages/rs-drive-abci/src/query/document_query/v1/tests.rs b/packages/rs-drive-abci/src/query/document_query/v1/tests.rs index 475419587a2..7368ebda5e0 100644 --- a/packages/rs-drive-abci/src/query/document_query/v1/tests.rs +++ b/packages/rs-drive-abci/src/query/document_query/v1/tests.rs @@ -3471,6 +3471,88 @@ mod having_range_tests { } } + /// The `IN`-pinned form end to end on the wire: `WHERE identityId + /// IN [X, Y] GROUP BY class HAVING AVG(grade) > 80 LIMIT 10` fans + /// out across both identities' secondaries and answers one merged + /// `ResultData.ranked` page whose entries carry `in_key`; the + /// proved variant returns the branch container as its Proof + /// payload. Merge/proof semantics are pinned in rs-drive's suites; + /// this pins the wire encoding, routing, and `in_key` mapping. + #[test] + fn in_pinned_having_is_served_end_to_end() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let contract = register_grades_compound(&platform, version); + let identity_x = [1u8; 32]; + let identity_y = [2u8; 32]; + insert_grade_docs( + &platform, + &contract, + 21_000, + &[ + (identity_x, "art", 90), + (identity_x, "math", 60), + (identity_y, "science", 95), + ], + version, + ); + + let mut request = having_request( + &contract, + "grade", + select(v1_select::Function::Avg, "grade"), + hc( + having_aggregate::Function::Avg, + "grade", + having_clause::Operator::GreaterThan, + Value::U64(80), + ), + Vec::new(), + Some(10), + false, + ); + request.group_by = vec!["class".to_string()]; + request.where_clauses = vec![wc( + "identityId", + ProtoWhereOperator::In, + Value::Array(vec![ + Value::Bytes(identity_y.to_vec()), + Value::Bytes(identity_x.to_vec()), + ]), + )]; + + let page = ranked_page(&platform, &state, request.clone(), version); + assert_eq!( + group_keys(&page.entries), + vec!["art", "science"], + "merged ascending: X's art (90) then Y's science (95); X's math \ + (60) misses the bound" + ); + assert_eq!( + page.entries + .iter() + .map(|e| e.in_key.clone()) + .collect::>(), + vec![Some(identity_x.to_vec()), Some(identity_y.to_vec())], + "merged entries carry their branch's in_key on the wire" + ); + + // The proved variant answers with a Proof payload (the branch + // container — decoded and verified client-side, pinned in + // rs-drive's tamper suite). + request.prove = true; + let result = platform + .query_documents_v1(request, &state, version) + .expect("query should succeed"); + assert!(result.errors.is_empty(), "got {:?}", result.errors); + match result.data { + Some(GetDocumentsResponseV1 { + result: Some(get_documents_response_v1::Result::Proof(proof)), + .. + }) => assert!(!proof.grovedb_proof.is_empty()), + other => panic!("expected a Proof response, got {:?}", other), + } + } + /// The pinned-prefix form end to end on the wire: `WHERE identityId /// = X GROUP BY class HAVING AVG(grade) > 80 LIMIT 10` routes to /// the same having executor, descends to X's terminal `class` tree, @@ -4004,7 +4086,7 @@ mod having_trust_boundary { document_type_name: "grade".to_string(), index, bounds: mode.bounds, - equality_prefix_values: Vec::new(), + prefix_branches: vec![Vec::new()], descending: mode.descending, limit: mode.limit, } diff --git a/packages/rs-drive-proof-verifier/src/proof/document_having.rs b/packages/rs-drive-proof-verifier/src/proof/document_having.rs index ea6069a6c10..eeedc8bb581 100644 --- a/packages/rs-drive-proof-verifier/src/proof/document_having.rs +++ b/packages/rs-drive-proof-verifier/src/proof/document_having.rs @@ -236,6 +236,7 @@ mod tests { fn count_entry(key: &str, count: u64) -> ProtoRankedEntry { ProtoRankedEntry { + in_key: None, key: key.as_bytes().to_vec(), value: Some(ranked_entry::Value::Count(count)), } diff --git a/packages/rs-drive-proof-verifier/src/proof/document_ranked.rs b/packages/rs-drive-proof-verifier/src/proof/document_ranked.rs index 63bd8d1e01e..41dff7cff3b 100644 --- a/packages/rs-drive-proof-verifier/src/proof/document_ranked.rs +++ b/packages/rs-drive-proof-verifier/src/proof/document_ranked.rs @@ -274,6 +274,9 @@ pub(crate) fn ranked_entry_from_proto(entry: &ProtoRankedEntry) -> Result ProtoRankedEntry { ProtoRankedEntry { + in_key: None, key: key.as_bytes().to_vec(), value: Some(ranked_entry::Value::Count(count)), } @@ -423,6 +427,7 @@ mod tests { /// that no fixed point maps to. fn avg_entry_raw(key: &str, avg: f64) -> ProtoRankedEntry { ProtoRankedEntry { + in_key: None, key: key.as_bytes().to_vec(), value: Some(ranked_entry::Value::Avg(avg)), } @@ -565,6 +570,7 @@ mod tests { #[test] fn decodes_signed_sum_entries() { let response = ranked_response(vec![ProtoRankedEntry { + in_key: None, key: b"refunds".to_vec(), value: Some(ranked_entry::Value::Sum(-1_000)), }]); @@ -665,6 +671,7 @@ mod tests { #[test] fn rejects_an_entry_with_no_value() { let response = ranked_response(vec![ProtoRankedEntry { + in_key: None, key: b"alpha".to_vec(), value: None, }]); @@ -733,10 +740,12 @@ mod tests { fn from_verified_carries_both_halves_of_the_page() { let entries = vec![ RankedEntry { + in_key: None, key: b"gamma".to_vec(), value: RankedEntryValue::Count(9), }, RankedEntry { + in_key: None, key: b"alpha".to_vec(), value: RankedEntryValue::Count(2), }, diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/batched_group_drain.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/batched_group_drain.rs index d81d73c4267..519455a2117 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/batched_group_drain.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/batched_group_drain.rs @@ -375,7 +375,7 @@ fn verified_page( ) .expect("the fixture declares this axis"), axis: axis.ranked, - equality_prefix_values: Vec::new(), + prefix_branches: vec![Vec::new()], descending: !ascending, k: 100, offset: 0, diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/ranked_index_e2e_tests.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/ranked_index_e2e_tests.rs index c4e30fd9927..9732cb2b4e9 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/ranked_index_e2e_tests.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/ranked_index_e2e_tests.rs @@ -1443,7 +1443,7 @@ fn verified_ranked_avg_page( document_type_name: "review".to_string(), index: find_ranked_index_for_axis(indexes, GROUP_PROPERTY, &[], RankedAxis::Avg, "grade") .expect("the fixture declares rankedAverageable on grade"), - equality_prefix_values: vec![], + prefix_branches: vec![vec![]], axis: RankedAxis::Avg, descending: true, k: limit as u16, diff --git a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs index c9188d91f93..ca8951507a5 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs @@ -11,6 +11,9 @@ //! Whole module is gated `feature = "server"` via the parent's //! `pub mod execute_range;` declaration. +use super::super::drive_document_ranked_query::branches::{ + encode_branch_proofs, merge_branch_pages, +}; use super::super::drive_document_ranked_query::{RankedAxis, RankedEntry, RankedEntryValue}; use super::{AxisRangeBounds, DriveDocumentHavingQuery}; use crate::drive::Drive; @@ -38,9 +41,37 @@ impl DriveDocumentHavingQuery<'_> { drive: &Drive, transaction: TransactionArg, platform_version: &PlatformVersion, + ) -> Result, Error> { + if self.prefix_branches.len() > 1 { + // One bounded walk per branch, each fetching up to the full + // limit (the merge lemma needs every branch's own in-bound + // prefix), merged with the shared comparator. + let per_branch = (0..self.prefix_branches.len()) + .map(|branch| { + self.execute_range_no_proof_branch(branch, drive, transaction, platform_version) + }) + .collect::, Error>>()?; + return merge_branch_pages( + per_branch, + &self.prefix_branches, + self.descending, + self.limit as usize, + ); + } + self.execute_range_no_proof_branch(0, drive, transaction, platform_version) + } + + /// One branch's in-bound page — the entire pre-`IN` executor, + /// parameterized by which prefix branch's terminal tree it walks. + fn execute_range_no_proof_branch( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error> { let grove_version = &platform_version.drive.grove_version; - let path = self.indexed_property_name_tree_path()?; + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); // Costs are destructured away rather than `.unwrap()`-ed, same @@ -61,6 +92,7 @@ impl DriveDocumentHavingQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(count, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Count(count), }) @@ -80,6 +112,7 @@ impl DriveDocumentHavingQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(sum, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Sum(sum), }) @@ -99,6 +132,7 @@ impl DriveDocumentHavingQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(avg, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::AvgFixedPoint(avg), }) @@ -141,9 +175,36 @@ impl DriveDocumentHavingQuery<'_> { drive: &Drive, transaction: TransactionArg, platform_version: &PlatformVersion, + ) -> Result, Error> { + if self.prefix_branches.len() > 1 { + // One indexed-axis range proof per branch, framed into the + // versioned container in canonical branch order. + let proofs = (0..self.prefix_branches.len()) + .map(|branch| { + self.execute_range_with_proof_branch( + branch, + drive, + transaction, + platform_version, + ) + }) + .collect::, Error>>()?; + return Ok(encode_branch_proofs(&proofs)); + } + self.execute_range_with_proof_branch(0, drive, transaction, platform_version) + } + + /// One branch's proof — the entire pre-`IN` prover, parameterized by + /// the prefix branch. + fn execute_range_with_proof_branch( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error> { let grove_version = &platform_version.drive.grove_version; - let path = self.indexed_property_name_tree_path()?; + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); let secondary_query = self.bounds.merk_query(self.descending); diff --git a/packages/rs-drive/src/query/drive_document_having_query/mod.rs b/packages/rs-drive/src/query/drive_document_having_query/mod.rs index f0418fc798a..15ebf3e5f40 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/mod.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/mod.rs @@ -73,11 +73,11 @@ use std::collections::BTreeMap; #[cfg(any(feature = "server", feature = "verify"))] use super::drive_document_ranked_query::index_picker::{ - encode_equality_prefix_values, find_ranked_index_for_axis, no_covering_index_message, + encode_prefix_branches, find_ranked_index_for_axis, no_covering_index_message, }; #[cfg(any(feature = "server", feature = "verify"))] use super::drive_document_ranked_query::{ - path::indexed_property_name_tree_path_for_index, RankedAxis, + path::indexed_property_name_tree_path_for_index, PrefixPin, RankedAxis, }; #[cfg(any(feature = "server", feature = "verify"))] use crate::error::query::QuerySyntaxError; @@ -247,7 +247,9 @@ pub struct DocumentHavingMode { /// exactly one per leading property of the covering compound index, /// in request order (the resolver re-orders them into index order /// when it encodes the path). Empty for the single-property form. - pub equality_pins: Vec<(String, Value)>, + /// At most one pin carries several values (the `IN` pin); see + /// [`PrefixPin`]. + pub prefix_pins: Vec, } /// A resolved having-range query. Shared by the prover and the verifier — @@ -267,15 +269,15 @@ pub struct DriveDocumentHavingQuery<'a> { pub document_type_name: String, /// The covering ranked index. Its **last** property is the `GROUP /// BY` property and the final path segment; any leading properties - /// are pinned by [`Self::equality_prefix_values`]. + /// are pinned by [`Self::prefix_branches`]. pub index: &'a Index, - /// Encoded index-key bytes of each leading index property's pinned - /// value, in index-property order — empty for a single-property - /// index. Part of the prover/verifier agreement exactly as on the - /// ranked surface: the segments feed straight into the shared path - /// builder. Produced by - /// [`super::drive_document_ranked_query::index_picker::encode_equality_prefix_values`]. - pub equality_prefix_values: Vec>, + /// The prefix **branches** — one inner `Vec>` of encoded + /// path segments per branch, in index-property order; always at + /// least one branch, several exactly when the request carried a + /// multi-element `IN` pin. Part of the prover/verifier agreement + /// exactly as on the ranked surface. Produced by + /// [`super::drive_document_ranked_query::index_picker::encode_prefix_branches`]. + pub prefix_branches: Vec>>, /// Inclusive bounds on the aggregate. Carry the axis; the index must /// declare the matching `ranked_*` flag. pub bounds: AxisRangeBounds, @@ -297,17 +299,17 @@ pub struct DriveDocumentHavingQuery<'a> { #[cfg(any(feature = "server", feature = "verify"))] impl DriveDocumentHavingQuery<'_> { - /// Path of the terminal property-name tree the axis secondary hangs - /// off — identical to the ranked surface's path (including the - /// pinned-prefix segments of a compound index), because both read - /// the same indexed tree. See + /// Path of one branch's terminal property-name tree — identical to + /// the ranked surface's path (including the pinned-prefix segments + /// of a compound index), because both read the same indexed + /// tree(s). See /// [`DriveDocumentRankedQuery::indexed_property_name_tree_path`](super::drive_document_ranked_query::DriveDocumentRankedQuery::indexed_property_name_tree_path). - pub fn indexed_property_name_tree_path(&self) -> Result>, Error> { + pub fn indexed_property_name_tree_path(&self, branch: usize) -> Result>, Error> { indexed_property_name_tree_path_for_index( &self.contract_id, &self.document_type_name, self.index, - &self.equality_prefix_values, + &self.prefix_branches[branch], ) } } @@ -338,9 +340,9 @@ pub fn resolve_having_query_for_mode<'a>( ) -> Result, Error> { let axis = mode.bounds.axis(); let pin_fields: Vec = mode - .equality_pins + .prefix_pins .iter() - .map(|(field, _)| field.clone()) + .map(|pin| pin.field.clone()) .collect(); let index = find_ranked_index_for_axis( indexes, @@ -355,19 +357,19 @@ pub fn resolve_having_query_for_mode<'a>( "having-range", axis, &mode.group_by_property, - &mode.equality_pins, + &mode.prefix_pins, &mode.aggregate_field, ), )) })?; - let equality_prefix_values = - encode_equality_prefix_values(document_type, index, &mode.equality_pins, platform_version)?; + let prefix_branches = + encode_prefix_branches(document_type, index, &mode.prefix_pins, platform_version)?; Ok(DriveDocumentHavingQuery { document_type, contract_id, document_type_name, index, - equality_prefix_values, + prefix_branches, bounds: mode.bounds, descending: mode.descending, limit: mode.limit, diff --git a/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs b/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs index 9cefa259130..0d20e3cb2e4 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs @@ -7,7 +7,7 @@ use super::{AxisRangeBounds, DocumentHavingMode, MAX_HAVING_LIMIT}; use crate::error::query::QuerySyntaxError; use crate::error::Error; use crate::query::drive_document_ranked_query::mode_detection::{ - equality_pins_from_where_clauses, ranked_order_key, + prefix_pins_from_where_clauses, ranked_order_key, }; use crate::query::drive_document_ranked_query::{RankedAxis, RankedPaginationInputs}; use crate::query::having::{ @@ -29,10 +29,12 @@ use grovedb::element::indexed::AVG_FIXED_POINT_SCALE; /// ``` /// /// with no `OFFSET`, no `START AT` / `START AFTER`, exactly one -/// `GROUP BY` property, `WHERE` clauses (when present) that are -/// equality pins on distinct properties — one per leading property of a -/// covering compound ranked index, selecting which prefix's secondary -/// the bound reads — exactly one `HAVING` clause whose aggregate +/// `GROUP BY` property, `WHERE` clauses (when present) that pin the +/// covering compound ranked index's leading properties — one clause per +/// property, each an equality, at most one of them an `IN` whose +/// elements fan the bound out across one prefix branch per element +/// (merged deterministically; see the ranked surface's +/// `prefix_pins_from_where_clauses`) — exactly one `HAVING` clause whose aggregate /// **is the selected aggregate** (same function, same field), an operator /// from the contiguous-range family (`=`, `>`, `>=`, `<`, `<=`, and the /// four `BETWEEN*` variants — `!=` and `IN` describe non-contiguous @@ -244,7 +246,7 @@ pub fn detect_having_mode_v0( // pin per leading property selects which prefix's secondary the // bound reads. Shape-only here; the index picker enforces the // exact-cover rule. - let equality_pins = equality_pins_from_where_clauses(where_clauses)?; + let prefix_pins = prefix_pins_from_where_clauses(where_clauses)?; // ---- LIMIT: required, 1 ..= MAX_HAVING_LIMIT --------------------- // @@ -312,7 +314,7 @@ pub fn detect_having_mode_v0( limit, group_by_property, aggregate_field, - equality_pins, + prefix_pins, }) } diff --git a/packages/rs-drive/src/query/drive_document_having_query/tests.rs b/packages/rs-drive/src/query/drive_document_having_query/tests.rs index 9bfd3277323..3904bebe0a4 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/tests.rs @@ -1496,10 +1496,12 @@ mod identifier_group_keys { entries, vec![ RankedEntry { + in_key: None, key: just_above.to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(161, 2)), }, RankedEntry { + in_key: None, key: well_above.to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(180, 2)), }, @@ -1817,10 +1819,12 @@ mod pinned_prefix { entries, vec![ RankedEntry { + in_key: None, key: b"english".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(161, 2)), }, RankedEntry { + in_key: None, key: b"art".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(180, 2)), }, @@ -1852,10 +1856,12 @@ mod pinned_prefix { y_entries, vec![ RankedEntry { + in_key: None, key: b"math".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(185, 2)), }, RankedEntry { + in_key: None, key: b"science".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(190, 2)), }, @@ -1893,29 +1899,54 @@ mod pinned_prefix { /// on a property that is not the index's leading property fails /// resolution. #[test] - fn in_prefix_and_wrong_pins_are_rejected() { + fn in_prefix_merges_branches_and_wrong_pins_are_rejected() { let (drive, contract) = setup_grades_compound_ranked(); insert_two_identities(&drive, &contract); + // `identityId IN [X, Y]` bounds each identity's own secondary + // and merges: ascending aggregate order, with every X entry + // (in_key = X's 32 bytes, all `1`s) sorting before Y's on the + // branch tie-break where aggregates tie. Bound is AVG > 80. let in_clause = vec![WhereClause { field: PREFIX_PROPERTY.to_string(), operator: WhereOperator::In, value: Value::Array(vec![ - Value::Identifier(IDENTITY_X), Value::Identifier(IDENTITY_Y), + Value::Identifier(IDENTITY_X), ]), }]; - let error = run(&drive, &contract, &in_clause, &[], false) - .expect_err("IN prefixes are not yet supported"); - match error { - Error::Query(QuerySyntaxError::Unsupported(message)) => { - assert!( - message.contains("IN") && message.contains("not yet supported"), - "the IN rejection must say it is a not-yet capability, got: {message}" - ); - } - other => panic!("expected Unsupported for an IN prefix, got {other:?}"), - } + let entries = entries_of( + run(&drive, &contract, &in_clause, &[], false).expect("the IN bound is served"), + ); + assert_eq!( + entries, + vec![ + RankedEntry { + in_key: Some(IDENTITY_X.to_vec()), + key: b"english".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(161, 2)), + }, + RankedEntry { + in_key: Some(IDENTITY_X.to_vec()), + key: b"art".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(180, 2)), + }, + RankedEntry { + in_key: Some(IDENTITY_Y.to_vec()), + key: b"math".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(185, 2)), + }, + RankedEntry { + in_key: Some(IDENTITY_Y.to_vec()), + key: b"science".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(190, 2)), + }, + ], + "the merged bound: X's english 80.5 and art 90, then Y's math \ + 92.5 and science 95, in ascending aggregate order with \ + branch-tagged entries — element order in the request must \ + not matter" + ); // A pin on the wrong property: `grade` is not the index's // leading property, so nothing covers [grade, class]. @@ -2049,6 +2080,7 @@ mod pinned_prefix { assert_eq!( entries, vec![RankedEntry { + in_key: None, key: b"math".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(170, 2)), }], @@ -2091,8 +2123,8 @@ mod pinned_prefix { ) .expect("the compound index covers the null-pinned request"); assert_eq!( - query.equality_prefix_values, - vec![Vec::::new()], + query.prefix_branches, + vec![vec![Vec::::new()]], "a null pin must encode as the write path's empty segment" ); let (root_hash, verified) = query @@ -2108,4 +2140,160 @@ mod pinned_prefix { .expect("root hash must be readable"), ); } + + /// A `null` element mixed with a real value in one `IN` pin: the + /// null branch is the write path's empty segment, which sorts + /// **first** in canonical branch order, and the merged bound covers + /// both subtrees — proved through the branch container. + #[test] + fn a_mixed_null_in_pin_bounds_both_prefixes_and_proves() { + const TAGGED_DOCTYPE: &str = "taggedGrade"; + let (drive, contract) = setup_grades_compound_ranked(); + let pv = platform_version(); + let document_type = contract + .document_type_for_name(TAGGED_DOCTYPE) + .expect("taggedGrade doctype exists"); + + for (i, (tag, class, grade)) in [ + (None, "math", 90i64), + (Some("honors"), "math", 95), + (Some("honors"), "art", 60), + ] + .iter() + .enumerate() + { + let mut doc: Document = document_type + .random_document(Some(9000 + i as u64), pv) + .expect("random document"); + let mut props = BTreeMap::new(); + if let Some(tag) = tag { + props.insert("tag".to_string(), Value::Text(tag.to_string())); + } + props.insert(GROUP_PROPERTY.to_string(), Value::Text(class.to_string())); + props.insert("grade".to_string(), Value::I64(*grade)); + doc.set_properties(props); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert a tagged grade document"); + } + + let mixed_pin = vec![WhereClause { + field: "tag".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::Text("honors".to_string()), Value::Null]), + }]; + let group_by = vec![GROUP_PROPERTY.to_string()]; + let having = vec![clause( + HavingAggregateFunction::Avg, + "grade", + HavingOperator::GreaterThan, + Value::U64(80), + )]; + let request = |prove: bool| DocumentHavingRequest { + contract: &contract, + document_type, + group_by: &group_by, + select: SelectProjection::avg("grade"), + having: &having, + order_by: &[], + where_clauses: &mixed_pin, + limit: Some(10), + offset: None, + has_start_at: false, + prove, + }; + + let entries = match drive + .execute_document_having_request(request(false), None, pv) + .expect("the mixed-null IN bound is served") + { + DocumentHavingResponse::Entries(entries) => entries, + DocumentHavingResponse::Proof(_) => panic!("expected entries, got a proof"), + }; + assert_eq!( + entries, + vec![ + RankedEntry { + in_key: Some(Vec::new()), + key: b"math".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(90, 1)), + }, + RankedEntry { + in_key: Some(b"honors".to_vec()), + key: b"math".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(95, 1)), + }, + ], + "both prefixes' in-bound groups, ascending; the same group key \ + appears twice, disambiguated by in_key, with the null branch's \ + empty in_key present (not None)" + ); + + let proof = match drive + .execute_document_having_request(request(true), None, pv) + .expect("the mixed-null IN prove succeeds") + { + DocumentHavingResponse::Proof(proof) => proof, + DocumentHavingResponse::Entries(_) => panic!("expected a proof, got entries"), + }; + let mode = detect_having_mode( + &SelectProjection::avg("grade"), + &group_by, + &having, + &[], + &mixed_pin, + RankedPaginationInputs { + limit: Some(10), + offset: None, + has_start_at: false, + }, + pv, + ) + .expect("the mixed-null case is well-formed"); + let query = resolve_having_query_for_mode( + contract.id_ref().to_buffer(), + document_type, + TAGGED_DOCTYPE.to_string(), + contract + .document_types() + .get(TAGGED_DOCTYPE) + .expect("taggedGrade doctype exists") + .indexes(), + &mode, + pv, + ) + .expect("the compound index covers the mixed-null request"); + assert_eq!( + query.prefix_branches, + vec![vec![Vec::new()], vec![b"honors".to_vec()]], + "canonical branch order: the empty (null) segment first" + ); + let (root_hash, verified) = query + .verify_having_range_proof(&proof, pv) + .expect("the mixed-null branch container must verify"); + assert_eq!(verified, entries); + assert_eq!( + root_hash, + drive + .grove + .root_hash(None, &pv.drive.grove_version) + .unwrap() + .expect("root hash must be readable"), + ); + } } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs b/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs new file mode 100644 index 00000000000..253f866db65 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs @@ -0,0 +1,194 @@ +//! Branch mechanics for `IN`-pinned ranked / having-range queries — +//! shared by the executors (walk one secondary per branch, merge) and +//! the verifiers (verify one proof per branch, re-merge), so both sides +//! implement one comparator and one proof-container layout. +//! +//! ## Why a merge needs no proof of its own +//! +//! Each branch's walk is independently proved complete against the same +//! root hash, and the merged page is a *deterministic function* of the +//! branch pages: any union entry that precedes a returned entry in the +//! merge order is preceded, within its own branch, by fewer than `limit` +//! entries — so it is in its branch's returned page. The union's first +//! `limit` entries are therefore contained in the union of the branch +//! pages, and re-merging verified branch pages reconstructs a complete, +//! correctly ordered page. (This is the same argument for both surfaces: +//! "first `limit` in merge order restricted to the branch" is top-k for +//! ranked and the in-bound range prefix for having.) +//! +//! ## The merge order +//! +//! `(aggregate in walk direction, branch segment ascending, group key in +//! walk direction)`. The middle term is the canonical branch tie-break: +//! the **encoded** segment bytes of the branch's `IN` position, fixed +//! ascending regardless of walk direction, independent of the caller's +//! element order — which also makes `null` (the empty segment) sort +//! first deterministically. + +use super::{RankedEntry, RankedEntryValue}; +use crate::error::drive::DriveError; +use crate::error::Error; +use std::cmp::Ordering; + +/// Version byte of the branch-proof container. Bumped only with a +/// method-version bump on the prove/verify pair — the container is part +/// of the prover/verifier agreement, not a transport detail. +const BRANCH_PROOF_CONTAINER_VERSION: u8 = 1; + +/// The position (index into a branch's segment list) at which the +/// branches differ — the `IN` pin's position in the covering index's +/// leading properties. `None` when there is a single branch (no `IN`), +/// or when branches are degenerate duplicates (the encoder rejects +/// those, so it is unreachable off the resolver path). +pub fn varying_position(branches: &[Vec>]) -> Option { + let first = branches.first()?; + for other in &branches[1..] { + for (position, (a, b)) in first.iter().zip(other.iter()).enumerate() { + if a != b { + return Some(position); + } + } + } + None +} + +/// The `in_key` for one branch: the encoded segment at the varying +/// position. `None` for single-branch queries — entries of an un-branched +/// response carry no discriminator, keeping the shape byte-identical to +/// the pre-`IN` surface. +pub fn branch_in_key(branches: &[Vec>], branch: usize) -> Option> { + if branches.len() < 2 { + return None; + } + let position = varying_position(branches)?; + branches.get(branch)?.get(position).cloned() +} + +/// Compare two entries' aggregates on the same axis. The executors and +/// verifiers only ever merge entries of one axis, so a variant mismatch +/// is corrupted state, reported rather than ordered. +fn aggregate_cmp(a: &RankedEntryValue, b: &RankedEntryValue) -> Result { + match (a, b) { + (RankedEntryValue::Count(a), RankedEntryValue::Count(b)) => Ok(a.cmp(b)), + (RankedEntryValue::Sum(a), RankedEntryValue::Sum(b)) => Ok(a.cmp(b)), + (RankedEntryValue::AvgFixedPoint(a), RankedEntryValue::AvgFixedPoint(b)) => Ok(a.cmp(b)), + _ => Err(Error::Drive(DriveError::CorruptedDriveState( + "branch merge compared entries from different aggregate axes".to_string(), + ))), + } +} + +/// Merge per-branch pages into the final page: tag each entry with its +/// branch's `in_key`, order by the merge comparator, cut at `limit`. +/// +/// `per_branch` must be indexed identically to `branches` (the resolver +/// produces both in canonical branch order). Branch pages arrive sorted +/// by the walk; the merged set is small (≤ branches × limit), so a +/// plain total sort is used instead of a k-way heap — simpler to keep +/// byte-identical between server and verifier. +pub fn merge_branch_pages( + per_branch: Vec>, + branches: &[Vec>], + descending: bool, + limit: usize, +) -> Result, Error> { + let mut merged: Vec = Vec::with_capacity(per_branch.iter().map(Vec::len).sum()); + for (branch, entries) in per_branch.into_iter().enumerate() { + let in_key = branch_in_key(branches, branch); + merged.extend(entries.into_iter().map(|mut entry| { + entry.in_key = in_key.clone(); + entry + })); + } + let mut comparison_error: Option = None; + merged.sort_by(|a, b| { + let aggregate = match aggregate_cmp(&a.value, &b.value) { + Ok(ordering) => ordering, + Err(e) => { + comparison_error.get_or_insert(e); + Ordering::Equal + } + }; + let directional = |ordering: Ordering| { + if descending { + ordering.reverse() + } else { + ordering + } + }; + directional(aggregate) + .then_with(|| a.in_key.cmp(&b.in_key)) + .then_with(|| directional(a.key.cmp(&b.key))) + }); + if let Some(e) = comparison_error { + return Err(e); + } + merged.truncate(limit); + Ok(merged) +} + +/// Frame per-branch grovedb proofs into the single opaque byte string +/// the wire's `Proof` carries: version byte, `u16` branch count, then +/// each proof length-prefixed with a `u32` (all big-endian). Used only +/// when there are two or more branches — a single-branch proof stays +/// the raw grovedb envelope, byte-identical to the pre-`IN` surface. +pub fn encode_branch_proofs(proofs: &[Vec]) -> Vec { + let mut out = Vec::with_capacity(3 + proofs.iter().map(|p| 4 + p.len()).sum::()); + out.push(BRANCH_PROOF_CONTAINER_VERSION); + out.extend_from_slice(&(proofs.len() as u16).to_be_bytes()); + for proof in proofs { + out.extend_from_slice(&(proof.len() as u32).to_be_bytes()); + out.extend_from_slice(proof); + } + out +} + +/// Parse the branch-proof container, requiring exactly +/// `expected_branches` proofs — the verifier derives that count from +/// its own resolution of the request, so a server cannot drop or +/// duplicate a branch without the container failing to parse. Trailing +/// bytes are rejected: an envelope is exactly its declared content. +pub fn decode_branch_proofs(bytes: &[u8], expected_branches: usize) -> Result>, Error> { + let malformed = |what: &str| { + Error::Drive(DriveError::CorruptedDriveState(format!( + "branch-proof container: {what}" + ))) + }; + let (&version, mut rest) = bytes.split_first().ok_or_else(|| malformed("empty"))?; + if version != BRANCH_PROOF_CONTAINER_VERSION { + return Err(malformed(&format!( + "unknown container version {version}; expected {BRANCH_PROOF_CONTAINER_VERSION}" + ))); + } + if rest.len() < 2 { + return Err(malformed("truncated branch count")); + } + let (count_bytes, tail) = rest.split_at(2); + let count = u16::from_be_bytes([count_bytes[0], count_bytes[1]]) as usize; + rest = tail; + if count != expected_branches { + return Err(malformed(&format!( + "container carries {count} branch proofs; the request resolves to \ + {expected_branches} branches" + ))); + } + let mut proofs = Vec::with_capacity(count); + for _ in 0..count { + if rest.len() < 4 { + return Err(malformed("truncated proof length")); + } + let (len_bytes, tail) = rest.split_at(4); + let len = + u32::from_be_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize; + if tail.len() < len { + return Err(malformed("truncated proof body")); + } + let (proof, tail) = tail.split_at(len); + proofs.push(proof.to_vec()); + rest = tail; + } + if !rest.is_empty() { + return Err(malformed("trailing bytes after the declared proofs")); + } + Ok(proofs) +} diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs index fb31a6635ff..53f62a064d1 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs @@ -10,6 +10,7 @@ //! Whole module is gated `feature = "server"` via the parent's //! `pub mod execute_top_k;` declaration. +use super::branches::{encode_branch_proofs, merge_branch_pages}; use super::{DriveDocumentRankedQuery, RankedAxis, RankedEntry, RankedEntryValue, RankedPage}; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -49,9 +50,49 @@ impl DriveDocumentRankedQuery<'_> { drive: &Drive, transaction: TransactionArg, platform_version: &PlatformVersion, + ) -> Result { + if self.prefix_branches.len() > 1 { + // One walk per branch, each fetching a full page (the merge + // lemma needs every branch's own top-k), merged with the + // shared comparator. `offset` is grammar-rejected with `IN`, + // so `skipped` is always 0 here. + let per_branch = (0..self.prefix_branches.len()) + .map(|branch| { + Ok(self + .execute_top_k_no_proof_branch( + branch, + drive, + transaction, + platform_version, + )? + .entries) + }) + .collect::, Error>>()?; + let entries = merge_branch_pages( + per_branch, + &self.prefix_branches, + self.descending, + self.k as usize, + )?; + return Ok(RankedPage { + skipped: 0, + entries, + }); + } + self.execute_top_k_no_proof_branch(0, drive, transaction, platform_version) + } + + /// One branch's page — the entire pre-`IN` executor, parameterized + /// by which prefix branch's terminal tree it walks. + fn execute_top_k_no_proof_branch( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, ) -> Result { let grove_version = &platform_version.drive.grove_version; - let path = self.indexed_property_name_tree_path()?; + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); let offset = self.offset as u64; @@ -75,6 +116,7 @@ impl DriveDocumentRankedQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(count, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Count(count), }) @@ -93,6 +135,7 @@ impl DriveDocumentRankedQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(sum, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Sum(sum), }) @@ -111,6 +154,7 @@ impl DriveDocumentRankedQuery<'_> { .map_err(|e| Error::GroveDB(Box::new(e)))? .into_iter() .map(|(avg, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::AvgFixedPoint(avg), }) @@ -173,9 +217,38 @@ impl DriveDocumentRankedQuery<'_> { drive: &Drive, transaction: TransactionArg, platform_version: &PlatformVersion, + ) -> Result, Error> { + if self.prefix_branches.len() > 1 { + // One indexed-axis proof per branch, framed into the + // versioned container in canonical branch order. The + // verifier re-derives the branch set from the request, so a + // dropped, duplicated, or reordered branch fails there. + let proofs = (0..self.prefix_branches.len()) + .map(|branch| { + self.execute_top_k_with_proof_branch( + branch, + drive, + transaction, + platform_version, + ) + }) + .collect::, Error>>()?; + return Ok(encode_branch_proofs(&proofs)); + } + self.execute_top_k_with_proof_branch(0, drive, transaction, platform_version) + } + + /// One branch's proof — the entire pre-`IN` prover, parameterized by + /// the prefix branch. + fn execute_top_k_with_proof_branch( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error> { let grove_version = &platform_version.drive.grove_version; - let path = self.indexed_property_name_tree_path()?; + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); // Same destructure-don't-unwrap rationale as the no-proof arm. diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs index 5f5408fbf30..8e315b68916 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs @@ -7,7 +7,7 @@ //! and the SDK verifier both call these so they land on the same index //! (and therefore the same grove path) for the same request. -use super::{DocumentRankedMode, DriveDocumentRankedQuery, RankedAxis}; +use super::{DocumentRankedMode, DriveDocumentRankedQuery, PrefixPin, RankedAxis}; use crate::error::query::QuerySyntaxError; use crate::error::Error; use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; @@ -104,9 +104,9 @@ pub fn find_ranked_index_for_mode<'b>( mode: &DocumentRankedMode, ) -> Option<&'b Index> { let pin_fields: Vec = mode - .equality_pins + .prefix_pins .iter() - .map(|(field, _)| field.clone()) + .map(|pin| pin.field.clone()) .collect(); find_ranked_index_for_axis( indexes, @@ -152,19 +152,19 @@ pub fn resolve_ranked_query_for_mode<'a>( "ranked", mode.axis, &mode.group_by_property, - &mode.equality_pins, + &mode.prefix_pins, &mode.aggregate_field, ), )) })?; - let equality_prefix_values = - encode_equality_prefix_values(document_type, index, &mode.equality_pins, platform_version)?; + let prefix_branches = + encode_prefix_branches(document_type, index, &mode.prefix_pins, platform_version)?; Ok(DriveDocumentRankedQuery { document_type, contract_id, document_type_name, index, - equality_prefix_values, + prefix_branches, axis: mode.axis, descending: mode.descending, k: mode.k, @@ -182,17 +182,17 @@ pub fn no_covering_index_message( surface: &str, axis: RankedAxis, group_by_property: &str, - equality_pins: &[(String, Value)], + prefix_pins: &[PrefixPin], aggregate_field: &str, ) -> String { let pin_fields = || { - equality_pins + prefix_pins .iter() - .map(|(field, _)| field.as_str()) + .map(|pin| pin.field.as_str()) .collect::>() .join(", ") }; - let index_shape = if equality_pins.is_empty() { + let index_shape = if prefix_pins.is_empty() { format!("a single-property index on `{group_by_property}`") } else { format!( @@ -204,7 +204,7 @@ pub fn no_covering_index_message( format!( "no ranked index covers `group_by = [{group_by_property}]`{} on the {axis:?} axis \ for this {surface} query: the document type needs {index_shape} declaring `{}`{}", - if equality_pins.is_empty() { + if prefix_pins.is_empty() { String::new() } else { format!(" with equality pins on [{}]", pin_fields()) @@ -218,61 +218,105 @@ pub fn no_covering_index_message( ) } -/// Encode the equality pins into the grove path's prefix-value -/// segments: for each **leading** property of `index`, in index order, -/// the pinned value's index-key bytes -/// (`DocumentType::serialize_value_for_key` — the same encoding the -/// write path used to key that prefix's value tree). +/// Encode the resolved prefix pins into **branches** — one +/// `Vec>` of prefix path segments per branch, in index-property +/// order (the same order and encoding the write path used to key those +/// prefix value trees). A request with only `==` pins yields exactly +/// one branch; the (at most one) `IN` pin yields one branch per +/// element. /// /// This is part of the prover/verifier agreement: server executors and /// the SDK's proof helpers both come through here, so a pinned value -/// can only ever name one subtree, identically on both sides. +/// can only ever name one subtree — and a branch *set* only ever one +/// ordered subtree list — identically on both sides. Branch order is +/// canonical: ascending by encoded segment bytes, independent of the +/// caller's element order (which also makes `null`, the empty segment, +/// sort first deterministically). /// /// `index` must have been picked by [`find_ranked_index_for_axis`] /// against these same pins — every leading property is then guaranteed -/// a pin. A value the property's type cannot encode (a string against -/// an integer property, an out-of-range integer) is a caller error, -/// reported as a query-syntax rejection naming the property. -pub fn encode_equality_prefix_values( +/// a pin. A value the property's type cannot encode is a caller error +/// naming the property; two `IN` elements that encode to the same +/// segment (two spellings of one value) are one branch and are rejected +/// as a duplicate rather than walked twice. +pub fn encode_prefix_branches( document_type: DocumentTypeRef, index: &Index, - equality_pins: &[(String, Value)], + prefix_pins: &[PrefixPin], platform_version: &PlatformVersion, -) -> Result>, Error> { +) -> Result>>, Error> { let leading = &index.properties[..index.properties.len().saturating_sub(1)]; - leading + let per_property: Vec>> = leading .iter() .map(|property| { - let (_, value) = equality_pins + let pin = prefix_pins .iter() - .find(|(field, _)| field == &property.name) + .find(|pin| pin.field == property.name) .ok_or_else(|| { Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( "internal resolution mismatch: the picked compound ranked index has \ - a leading property with no equality pin — the index picker and the \ - prefix encoder disagreed on the pins", + a leading property with no pin — the index picker and the prefix \ + encoder disagreed on the pins", )) })?; - // A null pin addresses the subtree the write walkers create - // for an **absent** value: they encode it as - // `get_raw_for_document_type(..).unwrap_or_default()` — an - // empty path segment — for user and system properties alike. - // Null must short-circuit here because the system-property - // encoders (`$updatedAt`, `$creatorId`, …) reject null before - // any encoding happens, which would make the stored - // empty-segment prefix unaddressable. - if value.is_null() { - return Ok(Vec::new()); - } - document_type - .serialize_value_for_key(&property.name, value, platform_version) - .map_err(|e| { - Error::Query(QuerySyntaxError::InvalidParameter(format!( - "the equality pin on `{}` does not encode as that property's \ - index key: {e}", - property.name - ))) + let mut encoded = pin + .values + .iter() + .map(|value| { + // A null pin addresses the subtree the write walkers + // create for an **absent** value: they encode it as + // `get_raw_for_document_type(..).unwrap_or_default()` + // — an empty path segment — for user and system + // properties alike. Null must short-circuit here + // because the system-property encoders (`$updatedAt`, + // `$creatorId`, …) reject null before any encoding + // happens, which would make the stored empty-segment + // prefix unaddressable. + if value.is_null() { + return Ok(Vec::new()); + } + document_type + .serialize_value_for_key(&property.name, value, platform_version) + .map_err(|e| { + Error::Query(QuerySyntaxError::InvalidParameter(format!( + "the pin on `{}` does not encode as that property's \ + index key: {e}", + property.name + ))) + }) }) + .collect::, Error>>()?; + if encoded.len() > 1 { + encoded.sort(); + if encoded.windows(2).any(|pair| pair[0] == pair[1]) { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "an `IN` pin's elements encode to the same index key: two \ + spellings of one value are one prefix branch — deduplicate \ + the element list", + ), + )); + } + } + Ok(encoded) }) - .collect() + .collect::, Error>>()?; + + // The grammar admits at most one multi-value pin, so this product + // is |IN| branches (or exactly one), already in canonical order + // because the only varying position was sorted above. + let mut branches: Vec>> = vec![Vec::with_capacity(leading.len())]; + for candidates in per_property { + branches = branches + .into_iter() + .flat_map(|prefix| { + candidates.iter().map(move |segment| { + let mut branch = prefix.clone(); + branch.push(segment.clone()); + branch + }) + }) + .collect(); + } + Ok(branches) } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/mod.rs b/packages/rs-drive/src/query/drive_document_ranked_query/mod.rs index fed2b5dffbd..c078d5ad853 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/mod.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/mod.rs @@ -82,6 +82,8 @@ use dpp::platform_value::Value; #[cfg(any(feature = "server", feature = "verify"))] pub use grovedb::element::indexed::AVG_FIXED_POINT_SCALE as RANKED_AVG_SCALE; +#[cfg(any(feature = "server", feature = "verify"))] +pub mod branches; #[cfg(any(feature = "server", feature = "verify"))] pub mod index_picker; #[cfg(any(feature = "server", feature = "verify"))] @@ -125,6 +127,20 @@ mod tests; #[cfg(any(feature = "server", feature = "verify"))] pub const MAX_RANKED_LIMIT: u16 = 100; +/// Hard ceiling on the element count of the (at most one) `IN` prefix +/// pin — the number of prefix **branches** one ranked / having-range +/// request may fan out into. +/// +/// Each element is one full secondary walk and one proof branch, each +/// carrying up to `limit` committed entries plus boundary commitments, +/// so worst-case proof size is `MAX_PREFIX_IN_BRANCHES × +/// MAX_RANKED_LIMIT` entries (≈100–150 KB at the ceiling). A hard +/// rejection rather than a clamp, for the same reason as the limit: the +/// branch set is echoed in the proof container and re-checked by the +/// verifier. +#[cfg(any(feature = "server", feature = "verify"))] +pub const MAX_PREFIX_IN_BRANCHES: usize = 10; + /// The `ORDER BY` field name that means "the group's `COUNT(*)`". /// /// `COUNT(*)` has no field to name, so the ranked grammar needs some @@ -254,6 +270,13 @@ pub struct RankedEntry { pub key: Vec, /// The group's aggregate on the requested axis. pub value: RankedEntryValue, + /// The branch this entry came from, on an `IN`-pinned request: the + /// encoded index-key segment of the `IN` position's pinned value + /// (empty bytes for the `null` branch). `None` on single-branch + /// responses — the same group key can appear under two prefixes, so + /// only a merged page needs the discriminator. See + /// [`branches::branch_in_key`]. + pub in_key: Option>, } /// A resolved ranked query. Shared by the prover and the verifier — both @@ -277,17 +300,20 @@ pub struct DriveDocumentRankedQuery<'a> { pub document_type_name: String, /// The covering ranked index. Its **last** property is the `GROUP /// BY` property and the final path segment; any leading properties - /// are pinned by [`Self::equality_prefix_values`]. + /// are pinned by [`Self::prefix_branches`]. pub index: &'a Index, - /// Encoded index-key bytes of each leading index property's pinned - /// value, in index-property order — empty for a single-property - /// index. Together with `index` these determine the grove path - /// (each leading property contributes a name segment and a value - /// segment), so they are as much a part of the prover/verifier - /// agreement as the path builder itself. Produced by - /// [`index_picker::encode_equality_prefix_values`] from the - /// request's equality `where` pins. - pub equality_prefix_values: Vec>, + /// The prefix **branches** — one inner `Vec>` of encoded + /// index-key path segments per branch, each in index-property + /// order. Always at least one branch; a single-property index or an + /// all-`==` pinned request has exactly one (possibly empty) branch, + /// and the (at most one) `IN` pin contributes one branch per + /// element, in canonical encoded-ascending order. Together with + /// `index` these determine the grove path(s), so the branch set is + /// as much a part of the prover/verifier agreement as the path + /// builder itself. Produced by + /// [`index_picker::encode_prefix_branches`] from the request's + /// `where` pins. + pub prefix_branches: Vec>>, /// Which aggregate the groups are ranked by. Must be covered by /// `index`'s matching `ranked_*` flag. pub axis: RankedAxis, @@ -409,12 +435,27 @@ pub struct DocumentRankedMode { /// [`RankedAxis::Count`] (`COUNT(*)`); the index's `summable` /// property for [`RankedAxis::Sum`] / [`RankedAxis::Avg`]. pub aggregate_field: String, - /// The equality `where` pins, `(property, value)` per clause — - /// exactly one per leading property of the covering compound index, - /// in whatever order the request supplied them (the resolver - /// re-orders them into index-property order when it encodes the - /// path). Empty for the single-property form. Shape-validated only: - /// the index-aware checks (does a compound index exist whose leading - /// properties these pin?) live in [`index_picker`]. - pub equality_pins: Vec<(String, Value)>, + /// The `where` pins — exactly one per leading property of the + /// covering compound index, in whatever order the request supplied + /// them (the resolver re-orders them into index-property order when + /// it encodes the path). Empty for the single-property form. + /// Shape-validated only: the index-aware checks (does a compound + /// index exist whose leading properties these pin?) live in + /// [`index_picker`]. + pub prefix_pins: Vec, +} + +/// One pinned leading property of the covering compound index. +/// +/// An `==` clause pins exactly one value; the (at most one) `IN` clause +/// pins several, each element selecting its own prefix **branch** — the +/// executors walk one secondary per branch and merge deterministically. +/// A single-element `IN` is normalized to an equality pin at grammar +/// time, so `values.len() > 1` is exactly "this is the branching pin". +#[derive(Debug, Clone, PartialEq)] +pub struct PrefixPin { + /// The pinned property's name. + pub field: String, + /// The pinned value(s); never empty. + pub values: Vec, } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/mod.rs b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/mod.rs index 17b2d46b5f5..2c80fe16696 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/mod.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/mod.rs @@ -88,4 +88,4 @@ pub fn ranked_order_key(select: &SelectProjection) -> &str { mod v0; // Re-exported so the dispatcher's callers (`drive_dispatcher`, the // test suites) keep addressing the frozen grammar by its old path. -pub use v0::{detect_ranked_mode_v0, equality_pins_from_where_clauses}; +pub use v0::{detect_ranked_mode_v0, prefix_pins_from_where_clauses}; diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs index 8a96f033b47..18a5892d9b4 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs @@ -3,6 +3,7 @@ //! this file is a v0 internal: a later grammar version gets its own //! `vN/` sibling rather than editing this one. +use super::super::{PrefixPin, MAX_PREFIX_IN_BRANCHES}; use super::ranked_order_key; use super::{ DocumentRankedMode, RankedAxis, RankedPaginationInputs, MAX_RANKED_LIMIT, @@ -22,46 +23,26 @@ use dpp::platform_value::Value; /// Both surfaces read a compound index's per-prefix secondary by /// descending through one prefix value tree per **leading** index /// property, and only an equality clause names a single value tree to -/// descend into. So the grammar is: every `where` clause must be an -/// equality (`==`), each on a distinct property. `IN` is rejected -/// separately from the other operators because it *will* eventually be -/// serviceable (one branch per element, once multi-`IN` branching lands -/// on the document query surface) — the message says so — while a range -/// operator on a prefix property can never pin a single subtree. +/// descend into. So the grammar is: every `where` clause is an equality +/// (`==`) on a distinct property, except that **at most one** clause may +/// be an `IN` — each of its elements selects its own prefix *branch*, +/// and the executors walk one secondary per branch and merge (see +/// [`MAX_PREFIX_IN_BRANCHES`] for the fan-out ceiling). A +/// range operator on a prefix property can never pin a subtree and is +/// rejected outright. A single-element `IN` is normalized to an +/// equality pin, so the degenerate case is byte-identical to `==`. /// /// Shape-only, like everything in this module: whether the pinned /// properties are exactly the leading properties of a covering compound -/// index is the index picker's call. -pub fn equality_pins_from_where_clauses( +/// index is the index picker's call, and element distinctness is +/// enforced post-encoding by the prefix encoder (two spellings of one +/// value are one branch, and must be rejected as a duplicate). +pub fn prefix_pins_from_where_clauses( where_clauses: &[WhereClause], -) -> Result, Error> { - let mut pins: Vec<(String, Value)> = Vec::with_capacity(where_clauses.len()); +) -> Result, Error> { + let mut pins: Vec = Vec::with_capacity(where_clauses.len()); + let mut branching_field: Option<&str> = None; for clause in where_clauses { - match clause.operator { - WhereOperator::Equal => {} - WhereOperator::In => { - return Err(Error::Query(QuerySyntaxError::Unsupported(format!( - "`{} IN …` is not yet supported on a ranked / having-range query's \ - prefix properties: each `IN` element names a different prefix value \ - tree, so serving it means one secondary walk per element and a merged \ - result — a future capability layered on multi-`IN` branching. Pin \ - each leading index property with `==`, or issue one request per \ - value.", - clause.field - )))); - } - _ => { - return Err(Error::Query( - QuerySyntaxError::InvalidWhereClauseComponents( - "a ranked / having-range query's `where` clauses must pin the covering \ - compound index's leading properties with `==`: the per-prefix \ - secondary lives under one prefix value tree per leading property, and \ - only an equality names a single value tree to descend into — a range \ - operator cannot pin a prefix", - ), - )); - } - } if clause.field.is_empty() { return Err(Error::Query( QuerySyntaxError::InvalidWhereClauseComponents( @@ -69,15 +50,72 @@ pub fn equality_pins_from_where_clauses( ), )); } - if pins.iter().any(|(field, _)| field == &clause.field) { + if pins.iter().any(|pin| pin.field == clause.field) { return Err(Error::Query( QuerySyntaxError::InvalidWhereClauseComponents( "a ranked / having-range query pins the same property twice: each leading \ - index property takes exactly one equality pin", + index property takes exactly one pin", ), )); } - pins.push((clause.field.clone(), clause.value.clone())); + let values = match clause.operator { + WhereOperator::Equal => vec![clause.value.clone()], + WhereOperator::In => { + if let Some(first) = branching_field { + return Err(Error::Query(QuerySyntaxError::Unsupported(format!( + "a ranked / having-range query takes at most one `IN` across its \ + prefix properties (`{first}` already carries it): several `IN`s \ + multiply into a cartesian product of prefix branches, each a \ + separate secondary walk inside one proof — a fan-out the branch \ + ceiling exists to prevent. Pin `{}` with `==`.", + clause.field + )))); + } + let Value::Array(elements) = &clause.value else { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "an `IN` pin's right operand must be an array of candidate values", + ), + )); + }; + if elements.is_empty() { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "an `IN` pin's element list is empty: it can match nothing, and \ + a pin that cannot match any prefix is a caller error", + ), + )); + } + if elements.len() > MAX_PREFIX_IN_BRANCHES { + return Err(Error::Query(QuerySyntaxError::InvalidParameter(format!( + "an `IN` pin fans out into one secondary walk (and one proof \ + branch) per element; {} elements exceeds the ceiling of {}. \ + Split the request.", + elements.len(), + MAX_PREFIX_IN_BRANCHES + )))); + } + if elements.len() > 1 { + branching_field = Some(clause.field.as_str()); + } + elements.clone() + } + _ => { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "a ranked / having-range query's `where` clauses must pin the covering \ + compound index's leading properties with `==` (or one `IN`): the \ + per-prefix secondary lives under one prefix value tree per leading \ + property, and only equality names value trees to descend into — a \ + range operator cannot pin a prefix", + ), + )); + } + }; + pins.push(PrefixPin { + field: clause.field.clone(), + values, + }); } Ok(pins) } @@ -98,7 +136,7 @@ pub fn equality_pins_from_where_clauses( /// `m ≥ 0`. `WHERE` clauses, when present, must be **equality pins** on /// distinct properties — one per leading property of a covering /// compound ranked index (see -/// [`equality_pins_from_where_clauses`]); the ranking then reads that +/// [`prefix_pins_from_where_clauses`]); the ranking then reads that /// pinned prefix's own secondary. With no `where` the covering index is /// single-property, exactly as before. /// @@ -263,7 +301,7 @@ pub fn detect_ranked_mode_v0( // serve). Anything other than a distinct-property equality is // rejected loudly here; whether the pinned set matches a covering // index's leading properties exactly is the index picker's call. - let equality_pins = equality_pins_from_where_clauses(where_clauses)?; + let prefix_pins = prefix_pins_from_where_clauses(where_clauses)?; // ---- LIMIT: required, 1 ..= MAX_RANKED_LIMIT --------------------- // @@ -321,6 +359,24 @@ pub fn detect_ranked_mode_v0( ))); } + // ---- OFFSET × IN: mutually exclusive ----------------------------- + // + // Rank-skip is served from counted subtree commitments *inside one + // secondary*; there is no counted structure spanning a branch + // union, so a cross-branch offset would have to walk (and prove) + // the skipped region in every branch — silently expensive. Callers + // who need deep pages issue per-prefix requests, where offset works + // exactly as documented. + if offset > 0 && prefix_pins.iter().any(|pin| pin.values.len() > 1) { + return Err(Error::Query(QuerySyntaxError::InvalidLimit( + "`OFFSET` cannot combine with an `IN` prefix pin: rank-skip is attested from \ + one secondary's counted commitments, and an `IN` merges several secondaries \ + with no counted structure over the union. Page one prefix at a time (`==` \ + pin + `OFFSET`), or drop the offset." + .to_string(), + ))); + } + Ok(DocumentRankedMode { axis, descending, @@ -328,6 +384,6 @@ pub fn detect_ranked_mode_v0( offset, group_by_property, aggregate_field, - equality_pins, + prefix_pins, }) } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/path.rs b/packages/rs-drive/src/query/drive_document_ranked_query/path.rs index ed3dccf0620..ec737825776 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/path.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/path.rs @@ -101,12 +101,15 @@ impl DriveDocumentRankedQuery<'_> { /// Errors when the number of encoded prefix values does not match /// the index's leading-property count — the fail-closed backstop /// for a caller that resolved the query against the wrong index. - pub fn indexed_property_name_tree_path(&self) -> Result>, Error> { + /// + /// `branch` indexes into [`Self::prefix_branches`]; single-branch + /// queries (no `IN` pin) always pass `0`. + pub fn indexed_property_name_tree_path(&self, branch: usize) -> Result>, Error> { indexed_property_name_tree_path_for_index( &self.contract_id, &self.document_type_name, self.index, - &self.equality_prefix_values, + &self.prefix_branches[branch], ) } } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs index 4a477c98195..5156be02704 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs @@ -494,9 +494,9 @@ fn sum_and_avg_selects_require_a_field() { /// properties. Detection is shape-only: an equality clause becomes a /// pin (whether a compound index actually covers it is the resolver's /// call — see `pins_without_a_covering_compound_index_are_rejected`); -/// anything that is not a distinct-property equality is refused -/// loudly, `IN` with its own not-yet message because it will become -/// serviceable once multi-`IN` branching lands. +/// anything that is not a distinct-property equality — or the one +/// permitted `IN`, which resolves to a multi-value branching pin — is +/// refused loudly. #[test] fn where_clauses_resolve_to_equality_pins_and_reject_everything_else() { // Equality pin: accepted at detection, carried in the mode. @@ -515,8 +515,11 @@ fn where_clauses_resolve_to_equality_pins_and_reject_everything_else() { ) .expect("an equality pin is a well-formed prefix pin"); assert_eq!( - mode.equality_pins, - vec![("chefId".to_string(), Value::Text("alpha".to_string()))] + mode.prefix_pins, + vec![PrefixPin { + field: "chefId".to_string(), + values: vec![Value::Text("alpha".to_string())], + }] ); // A range operator can never pin a single prefix value tree. @@ -539,14 +542,17 @@ fn where_clauses_resolve_to_equality_pins_and_reject_everything_else() { Error::Query(QuerySyntaxError::InvalidWhereClauseComponents(_)) )); - // `IN` is rejected with its own message: v1 pins are equality-only, - // multi-`IN` branching is a future capability. + // `IN` resolves to a branching pin — one value per element — and a + // single-element `IN` is exactly an equality pin. let in_clause = vec![WhereClause { field: "chefId".to_string(), operator: WhereOperator::In, - value: Value::Array(vec![Value::Text("alpha".to_string())]), + value: Value::Array(vec![ + Value::Text("beta".to_string()), + Value::Text("alpha".to_string()), + ]), }]; - let error = detect_ranked_mode_v0( + let mode = detect_ranked_mode_v0( &SelectProjection::avg("grade"), &group_by(), &[], @@ -554,16 +560,19 @@ fn where_clauses_resolve_to_equality_pins_and_reject_everything_else() { &in_clause, page(Some(2), None), ) - .expect_err("IN prefixes are not yet supported"); - match error { - Error::Query(QuerySyntaxError::Unsupported(message)) => { - assert!( - message.contains("IN") && message.contains("not yet supported"), - "the IN rejection must say it is a not-yet capability, got: {message}" - ); - } - other => panic!("expected Unsupported for an IN prefix, got {other:?}"), - } + .expect("an IN pin is a well-formed branching pin"); + assert_eq!( + mode.prefix_pins, + vec![PrefixPin { + field: "chefId".to_string(), + values: vec![ + Value::Text("beta".to_string()), + Value::Text("alpha".to_string()), + ], + }], + "the pin carries the elements verbatim; canonical branch order \ + is the encoder's job, not the grammar's" + ); // The same property pinned twice is a caller error, not a silent // last-write-wins. @@ -2118,7 +2127,7 @@ mod pinned_prefix { use super::super::drive_dispatcher::{DocumentRankedRequest, DocumentRankedResponse}; use super::super::index_picker::resolve_ranked_query_for_mode; - use super::super::mode_detection::detect_ranked_mode; + use super::super::mode_detection::{detect_ranked_mode, detect_ranked_mode_v0}; use super::super::{DriveDocumentRankedQuery, RankedEntry, RankedEntryValue}; use crate::drive::Drive; use crate::error::query::QuerySyntaxError; @@ -2332,10 +2341,12 @@ mod pinned_prefix { page.entries, vec![ RankedEntry { + in_key: None, key: b"art".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(180, 2)), }, RankedEntry { + in_key: None, key: b"english".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(161, 2)), }, @@ -2474,10 +2485,12 @@ mod pinned_prefix { page.entries, vec![ RankedEntry { + in_key: None, key: b"math".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(170, 2)), }, RankedEntry { + in_key: None, key: b"science".to_vec(), value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(60, 1)), }, @@ -2523,8 +2536,8 @@ mod pinned_prefix { ) .expect("the compound index covers the null-pinned request"); assert_eq!( - query.equality_prefix_values, - vec![Vec::::new()], + query.prefix_branches, + vec![vec![Vec::::new()]], "a null pin must encode as the write path's empty segment" ); let (root_hash, verified) = query @@ -2541,6 +2554,361 @@ mod pinned_prefix { ); } + fn in_pin(identities: &[[u8; 32]]) -> Vec { + vec![WhereClause { + field: PREFIX_PROPERTY.to_string(), + operator: WhereOperator::In, + value: Value::Array( + identities + .iter() + .map(|identity| Value::Identifier(*identity)) + .collect(), + ), + }] + } + + /// `identityId IN [X, Y]` walks each identity's own secondary and + /// merges: descending aggregate order, entries tagged with their + /// branch's `in_key`, and a **cross-prefix aggregate tie** breaking + /// by encoded prefix ascending (X's 32 `1`-bytes before Y's `2`s) — + /// the comparator's middle term, observable only here. The proof is + /// a branch container, round-tripped through the shared resolver + /// against the live root hash. + #[test] + fn in_pinned_top_k_merges_branches_and_proves() { + let (drive, contract) = setup_grades_compound_ranked(); + insert_grades( + &drive, + &contract, + &[ + // X: art 90, math 80. Y: science 95, history 90 — the + // two 90s are the cross-prefix tie. + (IDENTITY_X, "art", 90), + (IDENTITY_X, "math", 80), + (IDENTITY_Y, "science", 95), + (IDENTITY_Y, "history", 90), + ], + ); + + // Request order [Y, X] deliberately reversed: canonical branch + // order is by encoded prefix, not by element order. + let pins = in_pin(&[IDENTITY_Y, IDENTITY_X]); + let page = match run(&drive, &contract, &pins, 3, false).expect("read succeeds") { + DocumentRankedResponse::Entries(page) => page, + DocumentRankedResponse::Proof(_) => panic!("expected entries, got a proof"), + }; + assert_eq!(page.skipped, 0); + assert_eq!( + page.entries, + vec![ + RankedEntry { + in_key: Some(IDENTITY_Y.to_vec()), + key: b"science".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(95, 1)), + }, + RankedEntry { + in_key: Some(IDENTITY_X.to_vec()), + key: b"art".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(90, 1)), + }, + RankedEntry { + in_key: Some(IDENTITY_Y.to_vec()), + key: b"history".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(90, 1)), + }, + ], + "top 3 across the union: science 95, then the 90–90 tie broken \ + by encoded prefix ascending (X's art before Y's history)" + ); + + let proof = match run(&drive, &contract, &pins, 3, true).expect("prove succeeds") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof, got entries"), + }; + let query = client_side_query(&contract, &pins, 3); + assert_eq!(query.prefix_branches.len(), 2, "two branches resolved"); + let (root_hash, verified) = query + .verify_ranked_top_k_proof(&proof, platform_version()) + .expect("the branch container must verify"); + assert_eq!(verified.entries, page.entries); + assert_eq!( + root_hash, + drive + .grove + .root_hash(None, &platform_version().drive.grove_version) + .unwrap() + .expect("root hash must be readable"), + ); + } + + /// The tamper matrix on the branch container: a response whose + /// branch proofs are reordered, dropped, duplicated, re-versioned, + /// or padded must fail verification — never silently reorder or + /// shrink the merged page. + #[test] + fn tampered_branch_containers_do_not_verify() { + let (drive, contract) = setup_grades_compound_ranked(); + insert_grades( + &drive, + &contract, + &[(IDENTITY_X, "art", 90), (IDENTITY_Y, "science", 95)], + ); + let pins = in_pin(&[IDENTITY_X, IDENTITY_Y]); + let proof = match run(&drive, &contract, &pins, 2, true).expect("prove succeeds") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof, got entries"), + }; + let query = client_side_query(&contract, &pins, 2); + + // Baseline sanity: untampered verifies. + query + .verify_ranked_top_k_proof(&proof, platform_version()) + .expect("untampered container verifies"); + + // Decompose the container by hand: [version][u16 count]([u32 len][bytes])* + assert_eq!(proof[0], 1, "container version byte"); + let count = u16::from_be_bytes([proof[1], proof[2]]) as usize; + assert_eq!(count, 2); + let mut branch_proofs = Vec::new(); + let mut rest = &proof[3..]; + for _ in 0..count { + let len = u32::from_be_bytes([rest[0], rest[1], rest[2], rest[3]]) as usize; + branch_proofs.push(rest[4..4 + len].to_vec()); + rest = &rest[4 + len..]; + } + let reframe = |proofs: &[Vec]| { + let mut out = vec![1u8]; + out.extend_from_slice(&(proofs.len() as u16).to_be_bytes()); + for p in proofs { + out.extend_from_slice(&(p.len() as u32).to_be_bytes()); + out.extend_from_slice(p); + } + out + }; + + // Reordered: branch 0's proof is verified against branch 1's + // path and fails inside grovedb. + let reordered = reframe(&[branch_proofs[1].clone(), branch_proofs[0].clone()]); + assert!( + query + .verify_ranked_top_k_proof(&reordered, platform_version()) + .is_err(), + "reordered branch proofs must not verify" + ); + + // Dropped: count mismatch against the query's own resolution. + let dropped = reframe(&[branch_proofs[0].clone()]); + assert!( + query + .verify_ranked_top_k_proof(&dropped, platform_version()) + .is_err(), + "a dropped branch must not verify" + ); + + // Duplicated: same count, but branch 1's slot holds branch 0's + // proof — wrong path again. + let duplicated = reframe(&[branch_proofs[0].clone(), branch_proofs[0].clone()]); + assert!( + query + .verify_ranked_top_k_proof(&duplicated, platform_version()) + .is_err(), + "a duplicated branch proof must not verify" + ); + + // Unknown container version. + let mut reversioned = proof.clone(); + reversioned[0] = 2; + assert!( + query + .verify_ranked_top_k_proof(&reversioned, platform_version()) + .is_err(), + "an unknown container version must not verify" + ); + + // Trailing bytes after the declared proofs. + let mut padded = proof.clone(); + padded.push(0); + assert!( + query + .verify_ranked_top_k_proof(&padded, platform_version()) + .is_err(), + "trailing bytes must not verify" + ); + } + + /// A single-element `IN` is normalized to an equality pin at + /// grammar time: same resolved branch set, same entries, and the + /// **same proof bytes** — the degenerate case is byte-identical to + /// `==`, so no client can observe which spelling was used. + #[test] + fn single_element_in_is_byte_identical_to_an_equality_pin() { + let (drive, contract) = setup_grades_compound_ranked(); + insert_grades(&drive, &contract, &[(IDENTITY_X, "art", 90)]); + + let equality = pin(IDENTITY_X); + let single_in = in_pin(&[IDENTITY_X]); + + let eq_query = client_side_query(&contract, &equality, 2); + let in_query = client_side_query(&contract, &single_in, 2); + assert_eq!(eq_query.prefix_branches, in_query.prefix_branches); + + let eq_proof = match run(&drive, &contract, &equality, 2, true).expect("prove") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof"), + }; + let in_proof = match run(&drive, &contract, &single_in, 2, true).expect("prove") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof"), + }; + assert_eq!(eq_proof, in_proof, "no container for a single branch"); + + let eq_page = match run(&drive, &contract, &equality, 2, false).expect("read") { + DocumentRankedResponse::Entries(page) => page, + DocumentRankedResponse::Proof(_) => panic!("expected entries"), + }; + assert!( + eq_page.entries.iter().all(|e| e.in_key.is_none()), + "single-branch entries carry no in_key" + ); + } + + /// `OFFSET` is rejected together with an `IN` pin — rank-skip is + /// attested per-secondary and has no meaning across a branch union. + #[test] + fn offset_is_rejected_with_an_in_pin() { + let error = detect_ranked_mode_v0( + &SelectProjection::avg("grade"), + &vec![CLASS_PROPERTY.to_string()], + &[], + &[OrderClause { + field: "grade".to_string(), + ascending: false, + }], + &in_pin(&[IDENTITY_X, IDENTITY_Y]), + RankedPaginationInputs { + limit: Some(2), + offset: Some(1), + has_start_at: false, + }, + ) + .expect_err("offset cannot combine with IN"); + match error { + Error::Query(QuerySyntaxError::InvalidLimit(message)) => { + assert!( + message.contains("OFFSET") && message.contains("IN"), + "the rejection must name the offset × IN exclusion, got: {message}" + ); + } + other => panic!("expected InvalidLimit, got {other:?}"), + } + } + + /// Grammar rejections around the `IN` pin: over-cap element lists, + /// empty lists, a second `IN`, a non-array operand, and elements + /// that encode to the same segment. + #[test] + fn in_pin_shape_rejections() { + let detect = |where_clauses: &[WhereClause]| { + detect_ranked_mode_v0( + &SelectProjection::avg("grade"), + &vec![CLASS_PROPERTY.to_string()], + &[], + &[OrderClause { + field: "grade".to_string(), + ascending: false, + }], + where_clauses, + RankedPaginationInputs { + limit: Some(2), + offset: None, + has_start_at: false, + }, + ) + }; + + // Over the branch ceiling. + let identities: Vec<[u8; 32]> = (0..11).map(|i| [i as u8 + 1; 32]).collect(); + let error = detect(&in_pin(&identities)).expect_err("11 branches is over the cap"); + match error { + Error::Query(QuerySyntaxError::InvalidParameter(message)) => { + assert!( + message.contains("ceiling of 10"), + "the rejection must name the ceiling, got: {message}" + ); + } + other => panic!("expected InvalidParameter, got {other:?}"), + } + + // Empty element list. + let empty = vec![WhereClause { + field: PREFIX_PROPERTY.to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![]), + }]; + assert!(detect(&empty).is_err(), "an empty IN list must be rejected"); + + // A second IN (on another property) once one already branches. + let two_ins = vec![ + WhereClause { + field: PREFIX_PROPERTY.to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::Identifier(IDENTITY_X), + Value::Identifier(IDENTITY_Y), + ]), + }, + WhereClause { + field: "other".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::U64(1), Value::U64(2)]), + }, + ]; + let error = detect(&two_ins).expect_err("two branching INs must be rejected"); + assert!( + matches!(error, Error::Query(QuerySyntaxError::Unsupported(_))), + "expected Unsupported for a second IN, got {error:?}" + ); + + // Non-array operand. + let scalar = vec![WhereClause { + field: PREFIX_PROPERTY.to_string(), + operator: WhereOperator::In, + value: Value::U64(7), + }]; + assert!( + detect(&scalar).is_err(), + "a scalar IN operand must be rejected" + ); + + // Duplicate elements surface at the encoder (post-encoding + // distinctness), through the resolver. + let (_, contract) = setup_grades_compound_ranked(); + let duplicated = in_pin(&[IDENTITY_X, IDENTITY_X]); + let mode = detect(&duplicated).expect("shape-valid; duplicates are the encoder's call"); + let error = resolve_ranked_query_for_mode( + contract.id_ref().to_buffer(), + contract + .document_type_for_name(DOCUMENT_TYPE) + .expect("grade doctype exists"), + DOCUMENT_TYPE.to_string(), + contract + .document_types() + .get(DOCUMENT_TYPE) + .expect("grade doctype exists") + .indexes(), + &mode, + platform_version(), + ) + .expect_err("duplicate encoded elements must be rejected"); + assert!( + matches!( + error, + Error::Query(QuerySyntaxError::InvalidWhereClauseComponents(_)) + ), + "expected the duplicate-encoding rejection, got {error:?}" + ); + } + /// An unpinned request over the compound-only contract has no /// covering index — there is no global cross-prefix ordering to /// serve, so the rejection names the missing coverage. diff --git a/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs index fc9a0ab1727..3cde3cfb2b9 100644 --- a/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs @@ -1,5 +1,8 @@ use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::drive_document_ranked_query::branches::{ + decode_branch_proofs, merge_branch_pages, +}; use crate::query::{DriveDocumentHavingQuery, RankedAxis, RankedEntry, RankedEntryValue}; use crate::verify::RootHash; use grovedb::operations::proof::indexed_axis::AxisEntries; @@ -41,7 +44,54 @@ impl DriveDocumentHavingQuery<'_> { &self, proof: &[u8], ) -> Result<(RootHash, Vec), Error> { - let path = self.indexed_property_name_tree_path()?; + if self.prefix_branches.len() > 1 { + // `IN`-pinned request: same branch-container discipline as + // the ranked verifier — count from this query's own + // resolution, one root hash across branches, page re-derived + // by the shared merge. + let branch_proofs = decode_branch_proofs(proof, self.prefix_branches.len())?; + let mut root_hash: Option = None; + let mut per_branch = Vec::with_capacity(branch_proofs.len()); + for (branch, branch_proof) in branch_proofs.iter().enumerate() { + let (branch_root, entries) = + self.verify_having_range_proof_v0_branch(branch, branch_proof)?; + match root_hash { + None => root_hash = Some(branch_root), + Some(existing) if existing == branch_root => {} + Some(_) => { + return Err(Error::Drive(DriveError::CorruptedDriveState( + "branch proofs attest different root hashes: every branch of \ + one response must be proved against one platform state" + .to_string(), + ))); + } + } + per_branch.push(entries); + } + let entries = merge_branch_pages( + per_branch, + &self.prefix_branches, + self.descending, + self.limit as usize, + )?; + let root_hash = root_hash.ok_or_else(|| { + Error::Drive(DriveError::CorruptedDriveState( + "branch container verified to zero branches".to_string(), + )) + })?; + return Ok((root_hash, entries)); + } + self.verify_having_range_proof_v0_branch(0, proof) + } + + /// One branch's verification — the entire pre-`IN` verifier, + /// parameterized by the prefix branch. + fn verify_having_range_proof_v0_branch( + &self, + branch: usize, + proof: &[u8], + ) -> Result<(RootHash, Vec), Error> { + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); let secondary_query = self.bounds.merk_query(self.descending); @@ -71,6 +121,7 @@ impl DriveDocumentHavingQuery<'_> { (RankedAxis::Count, AxisEntries::Count(entries)) => entries .into_iter() .map(|(count, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Count(count), }) @@ -78,6 +129,7 @@ impl DriveDocumentHavingQuery<'_> { (RankedAxis::Sum, AxisEntries::Sum(entries)) => entries .into_iter() .map(|(sum, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Sum(sum), }) @@ -85,6 +137,7 @@ impl DriveDocumentHavingQuery<'_> { (RankedAxis::Avg, AxisEntries::Avg(entries)) => entries .into_iter() .map(|(avg, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::AvgFixedPoint(avg), }) diff --git a/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs index 668ab227770..7eb74a39585 100644 --- a/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs @@ -1,5 +1,8 @@ use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::drive_document_ranked_query::branches::{ + decode_branch_proofs, merge_branch_pages, +}; use crate::query::{ DriveDocumentRankedQuery, RankedAxis, RankedEntry, RankedEntryValue, RankedPage, }; @@ -53,7 +56,64 @@ impl DriveDocumentRankedQuery<'_> { &self, proof: &[u8], ) -> Result<(RootHash, RankedPage), Error> { - let path = self.indexed_property_name_tree_path()?; + if self.prefix_branches.len() > 1 { + // `IN`-pinned request: the proof bytes are the branch + // container. The branch count comes from *this* query's own + // resolution, so a container with a dropped, duplicated, or + // added branch fails to parse; a reordered or substituted + // branch proof fails its branch's own path verification; and + // all branches must attest one root hash. The page is then + // re-derived by the shared merge — the client never trusts a + // server-side merge. + let branch_proofs = decode_branch_proofs(proof, self.prefix_branches.len())?; + let mut root_hash: Option = None; + let mut per_branch = Vec::with_capacity(branch_proofs.len()); + for (branch, branch_proof) in branch_proofs.iter().enumerate() { + let (branch_root, page) = + self.verify_ranked_top_k_proof_v0_branch(branch, branch_proof)?; + match root_hash { + None => root_hash = Some(branch_root), + Some(existing) if existing == branch_root => {} + Some(_) => { + return Err(Error::Drive(DriveError::CorruptedDriveState( + "branch proofs attest different root hashes: every branch of \ + one response must be proved against one platform state" + .to_string(), + ))); + } + } + per_branch.push(page.entries); + } + let entries = merge_branch_pages( + per_branch, + &self.prefix_branches, + self.descending, + self.k as usize, + )?; + let root_hash = root_hash.ok_or_else(|| { + Error::Drive(DriveError::CorruptedDriveState( + "branch container verified to zero branches".to_string(), + )) + })?; + return Ok(( + root_hash, + RankedPage { + skipped: 0, + entries, + }, + )); + } + self.verify_ranked_top_k_proof_v0_branch(0, proof) + } + + /// One branch's verification — the entire pre-`IN` verifier, + /// parameterized by the prefix branch. + fn verify_ranked_top_k_proof_v0_branch( + &self, + branch: usize, + proof: &[u8], + ) -> Result<(RootHash, RankedPage), Error> { + let path = self.indexed_property_name_tree_path(branch)?; let path_refs: Vec<&[u8]> = path.iter().map(|segment| segment.as_slice()).collect(); let result = GroveDb::verify_indexed_axis_top_k_paginated( @@ -70,6 +130,7 @@ impl DriveDocumentRankedQuery<'_> { (RankedAxis::Count, AxisEntries::Count(entries)) => entries .into_iter() .map(|(count, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Count(count), }) @@ -77,6 +138,7 @@ impl DriveDocumentRankedQuery<'_> { (RankedAxis::Sum, AxisEntries::Sum(entries)) => entries .into_iter() .map(|(sum, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::Sum(sum), }) @@ -84,6 +146,7 @@ impl DriveDocumentRankedQuery<'_> { (RankedAxis::Avg, AxisEntries::Avg(entries)) => entries .into_iter() .map(|(avg, key)| RankedEntry { + in_key: None, key, value: RankedEntryValue::AvgFixedPoint(avg), }) diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 9015c19a583..6edeea0546c 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -732,7 +732,7 @@ impl MockResponse for drive_proof_verifier::DocumentSplitAverages { /// is already an `i128`. One numeric column keeps the tuple flat while /// the tag preserves which axis produced it, so a mock expectation /// can't quietly turn a count into a sum. -type DocumentRankedPage = (u64, Vec<(Vec, u8, i128)>); +type DocumentRankedPage = (u64, Vec<(Vec, u8, i128, Option>)>); const RANKED_TAG_COUNT: u8 = 0; const RANKED_TAG_SUM: u8 = 1; @@ -741,18 +741,21 @@ const RANKED_TAG_AVG: u8 = 2; impl MockResponse for drive_proof_verifier::DocumentRankedEntries { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { let bincode_config = standard(); - let triples: Vec<(Vec, u8, i128)> = self + let triples: Vec<(Vec, u8, i128, Option>)> = self .entries .iter() .map(|e| match e.value { - drive_proof_verifier::RankedEntryValue::Count(count) => { - (e.key.clone(), RANKED_TAG_COUNT, count as i128) - } + drive_proof_verifier::RankedEntryValue::Count(count) => ( + e.key.clone(), + RANKED_TAG_COUNT, + count as i128, + e.in_key.clone(), + ), drive_proof_verifier::RankedEntryValue::Sum(sum) => { - (e.key.clone(), RANKED_TAG_SUM, sum as i128) + (e.key.clone(), RANKED_TAG_SUM, sum as i128, e.in_key.clone()) } drive_proof_verifier::RankedEntryValue::AvgFixedPoint(avg) => { - (e.key.clone(), RANKED_TAG_AVG, avg) + (e.key.clone(), RANKED_TAG_AVG, avg, e.in_key.clone()) } }) .collect(); @@ -769,7 +772,7 @@ impl MockResponse for drive_proof_verifier::DocumentRankedEntries { bincode::decode_from_slice(buf, bincode_config).expect("decode DocumentRankedEntries"); let entries: Vec = triples .into_iter() - .map(|(key, tag, value)| { + .map(|(key, tag, value, in_key)| { let value = match tag { RANKED_TAG_COUNT => drive_proof_verifier::RankedEntryValue::Count( u64::try_from(value).expect("a Count entry round-trips through i128"), @@ -780,7 +783,7 @@ impl MockResponse for drive_proof_verifier::DocumentRankedEntries { RANKED_TAG_AVG => drive_proof_verifier::RankedEntryValue::AvgFixedPoint(value), other => panic!("unknown ranked axis tag {other} in mock expectation"), }; - drive_proof_verifier::RankedEntry { key, value } + drive_proof_verifier::RankedEntry { in_key, key, value } }) .collect(); drive_proof_verifier::DocumentRankedEntries { From 59a5afcd84626640fb1ce56422816fec209240bf Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 13 Aug 2026 22:24:57 +0700 Subject: [PATCH 2/5] fix(drive): satisfy workspace clippy under all-features Co-Authored-By: Claude Fable 5 --- .../rs-drive/src/query/drive_document_having_query/mod.rs | 2 -- .../src/query/drive_document_ranked_query/index_picker.rs | 1 - .../rs-drive/src/query/drive_document_ranked_query/tests.rs | 4 ++-- packages/rs-sdk/src/mock/requests.rs | 6 ++++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/rs-drive/src/query/drive_document_having_query/mod.rs b/packages/rs-drive/src/query/drive_document_having_query/mod.rs index 15ebf3e5f40..d1c56e56532 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/mod.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/mod.rs @@ -65,8 +65,6 @@ #[cfg(any(feature = "server", feature = "verify"))] use dpp::data_contract::document_type::{DocumentTypeRef, Index}; #[cfg(any(feature = "server", feature = "verify"))] -use dpp::platform_value::Value; -#[cfg(any(feature = "server", feature = "verify"))] use dpp::version::PlatformVersion; #[cfg(any(feature = "server", feature = "verify"))] use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs index 8e315b68916..63cc322e45b 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs @@ -12,7 +12,6 @@ use crate::error::query::QuerySyntaxError; use crate::error::Error; use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; use dpp::data_contract::document_type::{DocumentTypeRef, Index}; -use dpp::platform_value::Value; use dpp::version::PlatformVersion; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs index 5156be02704..5c590fa5197 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs @@ -2778,7 +2778,7 @@ mod pinned_prefix { fn offset_is_rejected_with_an_in_pin() { let error = detect_ranked_mode_v0( &SelectProjection::avg("grade"), - &vec![CLASS_PROPERTY.to_string()], + &[CLASS_PROPERTY.to_string()], &[], &[OrderClause { field: "grade".to_string(), @@ -2811,7 +2811,7 @@ mod pinned_prefix { let detect = |where_clauses: &[WhereClause]| { detect_ranked_mode_v0( &SelectProjection::avg("grade"), - &vec![CLASS_PROPERTY.to_string()], + &[CLASS_PROPERTY.to_string()], &[], &[OrderClause { field: "grade".to_string(), diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 6edeea0546c..8cd7c1c445d 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -732,7 +732,9 @@ impl MockResponse for drive_proof_verifier::DocumentSplitAverages { /// is already an `i128`. One numeric column keeps the tuple flat while /// the tag preserves which axis produced it, so a mock expectation /// can't quietly turn a count into a sum. -type DocumentRankedPage = (u64, Vec<(Vec, u8, i128, Option>)>); +/// One mock-serialized ranked entry: `(key, axis tag, value, in_key)`. +type MockRankedEntry = (Vec, u8, i128, Option>); +type DocumentRankedPage = (u64, Vec); const RANKED_TAG_COUNT: u8 = 0; const RANKED_TAG_SUM: u8 = 1; @@ -741,7 +743,7 @@ const RANKED_TAG_AVG: u8 = 2; impl MockResponse for drive_proof_verifier::DocumentRankedEntries { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { let bincode_config = standard(); - let triples: Vec<(Vec, u8, i128, Option>)> = self + let triples: Vec = self .entries .iter() .map(|e| match e.value { From eaccd9e91ff019b531be63816aba09f194014d37 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 13 Aug 2026 22:45:34 +0700 Subject: [PATCH 3/5] fix(drive): singleton IN normalization is clause-order independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The one-IN budget was charged before checking whether the current clause was a singleton, so `a IN [1,2] AND b IN [3]` rejected while the reversed order passed. Only multi-element INs now count against the budget, in either order — a singleton is an equality pin, as documented. Both orders pinned in in_pin_shape_rejections. Co-Authored-By: Claude Fable 5 --- .../mode_detection/v0/mod.rs | 24 ++++--- .../drive_document_ranked_query/tests.rs | 65 +++++++++++++------ 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs index 18a5892d9b4..464efb06ac7 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/mode_detection/v0/mod.rs @@ -61,16 +61,6 @@ pub fn prefix_pins_from_where_clauses( let values = match clause.operator { WhereOperator::Equal => vec![clause.value.clone()], WhereOperator::In => { - if let Some(first) = branching_field { - return Err(Error::Query(QuerySyntaxError::Unsupported(format!( - "a ranked / having-range query takes at most one `IN` across its \ - prefix properties (`{first}` already carries it): several `IN`s \ - multiply into a cartesian product of prefix branches, each a \ - separate secondary walk inside one proof — a fan-out the branch \ - ceiling exists to prevent. Pin `{}` with `==`.", - clause.field - )))); - } let Value::Array(elements) = &clause.value else { return Err(Error::Query( QuerySyntaxError::InvalidWhereClauseComponents( @@ -95,7 +85,21 @@ pub fn prefix_pins_from_where_clauses( MAX_PREFIX_IN_BRANCHES )))); } + // Only a multi-element `IN` branches; a singleton is an + // equality pin and never counts against the one-`IN` + // budget — in either clause order. if elements.len() > 1 { + if let Some(first) = branching_field { + return Err(Error::Query(QuerySyntaxError::Unsupported(format!( + "a ranked / having-range query takes at most one branching \ + `IN` across its prefix properties (`{first}` already carries \ + it): several `IN`s multiply into a cartesian product of \ + prefix branches, each a separate secondary walk inside one \ + proof — a fan-out the branch ceiling exists to prevent. Pin \ + `{}` with `==` or a single-element `IN`.", + clause.field + )))); + } branching_field = Some(clause.field.as_str()); } elements.clone() diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs index 5c590fa5197..0d1fdac7598 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs @@ -2847,27 +2847,50 @@ mod pinned_prefix { }]; assert!(detect(&empty).is_err(), "an empty IN list must be rejected"); - // A second IN (on another property) once one already branches. - let two_ins = vec![ - WhereClause { - field: PREFIX_PROPERTY.to_string(), - operator: WhereOperator::In, - value: Value::Array(vec![ - Value::Identifier(IDENTITY_X), - Value::Identifier(IDENTITY_Y), - ]), - }, - WhereClause { - field: "other".to_string(), - operator: WhereOperator::In, - value: Value::Array(vec![Value::U64(1), Value::U64(2)]), - }, - ]; - let error = detect(&two_ins).expect_err("two branching INs must be rejected"); - assert!( - matches!(error, Error::Query(QuerySyntaxError::Unsupported(_))), - "expected Unsupported for a second IN, got {error:?}" - ); + // Two *branching* INs are rejected in either clause order. + let multi = |field: &str| WhereClause { + field: field.to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::U64(1), Value::U64(2)]), + }; + for two_ins in [ + vec![multi(PREFIX_PROPERTY), multi("other")], + vec![multi("other"), multi(PREFIX_PROPERTY)], + ] { + let error = detect(&two_ins).expect_err("two branching INs must be rejected"); + assert!( + matches!(error, Error::Query(QuerySyntaxError::Unsupported(_))), + "expected Unsupported for a second branching IN, got {error:?}" + ); + } + + // A singleton IN is an equality pin and never counts against + // the one-`IN` budget — in either clause order relative to the + // branching one. + let singleton = WhereClause { + field: "other".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::U64(1)]), + }; + for mixed in [ + vec![multi(PREFIX_PROPERTY), singleton.clone()], + vec![singleton.clone(), multi(PREFIX_PROPERTY)], + ] { + let mode = detect(&mixed) + .expect("a singleton IN alongside a branching IN is well-formed either way"); + assert_eq!( + mode.prefix_pins + .iter() + .map(|pin| pin.values.len()) + .collect::>(), + if mixed[0].field == "other" { + vec![1, 2] + } else { + vec![2, 1] + }, + "one branching pin and one singleton pin, in clause order" + ); + } // Non-array operand. let scalar = vec![WhereClause { From 7cea92ff15ccda876130943ff55809dd49e7f339 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 14 Aug 2026 00:26:14 +0700 Subject: [PATCH 4/5] feat(drive)!: single branched grovedb envelope replaces the proof container The IN-pinned prove and verify paths now use grovedb's branched indexed-axis proofs (dashpay/grovedb#793): shared ancestor layers appear once, the branching level is one multi-key Merk proof binding every branch's value tree, each branch carries only its tail, and one root hash is reconstructed for the whole envelope. The length-prefixed container of per-branch proofs is deleted, along with the cross-branch root-hash equality assertion it required; the platform keeps the merge comparator, in_key tagging, and grove-path decomposition. grovedb pin bumped to the PR branch. The deep tamper matrix (reordered keys, duplicated or dropped tails, echo mismatches) moved to grovedb's own suite where the envelope now lives; the platform test pins corrupted and truncated bytes plus the two envelope shapes never cross-verifying. Review fixes folded in: encode_prefix_branches validates pin shape itself (non-empty values, at most one branching pin), branch indexing fails closed instead of panicking, and the no-covering-index and having-grammar docs describe the IN-inclusive pin rule. Co-Authored-By: Claude Fable 5 --- Cargo.lock | 50 ++--- packages/rs-dpp/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 8 +- packages/rs-drive/Cargo.toml | 12 +- .../execute_range.rs | 33 ++-- .../query/drive_document_having_query/mod.rs | 11 +- .../mode_detection/v0/mod.rs | 6 +- .../drive_document_ranked_query/branches.rs | 172 ++++++++++-------- .../execute_top_k.rs | 41 +++-- .../index_picker.rs | 32 +++- .../query/drive_document_ranked_query/path.rs | 13 +- .../drive_document_ranked_query/tests.rs | 91 ++++----- .../verify_having_range_proof/v0/mod.rs | 68 ++++--- .../verify_ranked_top_k_proof/v0/mod.rs | 75 ++++---- packages/rs-platform-version/Cargo.toml | 2 +- packages/rs-platform-wallet/Cargo.toml | 2 +- packages/rs-sdk/Cargo.toml | 2 +- 17 files changed, 348 insertions(+), 272 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6775bdd0c17..76f2992e59c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1229,7 +1229,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2475,7 +2475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2536,7 +2536,7 @@ checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2955,7 +2955,7 @@ dependencies = [ [[package]] name = "grovedb" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "axum 0.8.9", "bincode", @@ -2993,7 +2993,7 @@ dependencies = [ [[package]] name = "grovedb-bulk-append-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "blake3", @@ -3009,7 +3009,7 @@ dependencies = [ [[package]] name = "grovedb-commitment-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3025,7 +3025,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "integer-encoding", "intmap", @@ -3035,7 +3035,7 @@ dependencies = [ [[package]] name = "grovedb-dense-fixed-sized-merkle-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "blake3", @@ -3048,7 +3048,7 @@ dependencies = [ [[package]] name = "grovedb-element" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "bincode_derive", @@ -3063,7 +3063,7 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "grovedb-costs", "hex", @@ -3075,7 +3075,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "bincode_derive", @@ -3101,7 +3101,7 @@ dependencies = [ [[package]] name = "grovedb-merkle-mountain-range" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "blake3", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "grovedb-path" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "hex", ] @@ -3120,7 +3120,7 @@ dependencies = [ [[package]] name = "grovedb-query" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "bincode", "byteorder", @@ -3136,7 +3136,7 @@ dependencies = [ [[package]] name = "grovedb-storage" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "blake3", "grovedb-costs", @@ -3155,7 +3155,7 @@ dependencies = [ [[package]] name = "grovedb-version" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "thiserror 2.0.18", "versioned-feature-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3164,7 +3164,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "hex", "itertools 0.14.0", @@ -3173,7 +3173,7 @@ dependencies = [ [[package]] name = "grovedbg-types" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=a2791bbdca756d6a6113024aec48f09f7a33faa9#a2791bbdca756d6a6113024aec48f09f7a33faa9" +source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" dependencies = [ "serde", "serde_with 3.21.0", @@ -3840,7 +3840,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5752,7 +5752,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6560,7 +6560,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6573,7 +6573,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -6632,7 +6632,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -7492,7 +7492,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -8941,7 +8941,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 7a1c3bf85f7..eae4dabe34b 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -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 = "a2791bbdca756d6a6113024aec48f09f7a33faa9", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } [dev-dependencies] tokio = { version = "1.40", features = ["full"] } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 23069f0158e..aaa5827ed34 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -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 = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } nonempty = "0.11" # Shielded-pool snapshot needs raw RocksDB SstFileWriter + ingest_external_file_cf # bindings, and blake3 for the snapshot-file checksum. @@ -107,7 +107,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 = "a2791bbdca756d6a6113024aec48f09f7a33faa9", features = ["client"] } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", features = ["client"] } assert_matches = "1.5.0" drive-abci = { path = ".", features = ["testing-config", "mocks", "shielded_test_data"] } bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f" } @@ -121,8 +121,8 @@ integer-encoding = { version = "4.0.0" } # For dump_only_default_and_aux_cfs_under_shielded_subtree_prefix — same # subtree-prefix algorithm grovedb uses internally. -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } [features] default = ["bls-signatures"] diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index f04f8410396..c2278c8f482 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -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 = "a2791bbdca756d6a6113024aec48f09f7a33faa9", optional = true, default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9", optional = true } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9", optional = true } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true, default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } [dev-dependencies] criterion = "0.5" diff --git a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs index ca8951507a5..d6f7d8d0295 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs @@ -12,7 +12,7 @@ //! `pub mod execute_range;` declaration. use super::super::drive_document_ranked_query::branches::{ - encode_branch_proofs, merge_branch_pages, + decompose_branch_paths, merge_branch_pages, }; use super::super::drive_document_ranked_query::{RankedAxis, RankedEntry, RankedEntryValue}; use super::{AxisRangeBounds, DriveDocumentHavingQuery}; @@ -177,19 +177,26 @@ impl DriveDocumentHavingQuery<'_> { platform_version: &PlatformVersion, ) -> Result, Error> { if self.prefix_branches.len() > 1 { - // One indexed-axis range proof per branch, framed into the - // versioned container in canonical branch order. - let proofs = (0..self.prefix_branches.len()) - .map(|branch| { - self.execute_range_with_proof_branch( - branch, - drive, - transaction, - platform_version, - ) - }) + // One grovedb **branched** envelope — see the ranked + // executor's multi-branch arm for the shape. + let grove_version = &platform_version.drive.grove_version; + let paths = (0..self.prefix_branches.len()) + .map(|branch| self.indexed_property_name_tree_path(branch)) .collect::, Error>>()?; - return Ok(encode_branch_proofs(&proofs)); + let (prefix, keys, suffix) = decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let suffix_refs: Vec<&[u8]> = suffix.iter().map(|s| s.as_slice()).collect(); + let CostContext { value, cost: _ } = drive.grove.prove_indexed_axis_query_branched( + &prefix_refs, + &keys, + &suffix_refs, + self.bounds.axis().into(), + self.bounds.merk_query(self.descending), + Some(self.limit), + transaction, + grove_version, + ); + return value.map_err(|e| Error::GroveDB(Box::new(e))); } self.execute_range_with_proof_branch(0, drive, transaction, platform_version) } diff --git a/packages/rs-drive/src/query/drive_document_having_query/mod.rs b/packages/rs-drive/src/query/drive_document_having_query/mod.rs index d1c56e56532..964d264d3a4 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/mod.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/mod.rs @@ -78,6 +78,8 @@ use super::drive_document_ranked_query::{ path::indexed_property_name_tree_path_for_index, PrefixPin, RankedAxis, }; #[cfg(any(feature = "server", feature = "verify"))] +use crate::error::drive::DriveError; +#[cfg(any(feature = "server", feature = "verify"))] use crate::error::query::QuerySyntaxError; #[cfg(any(feature = "server", feature = "verify"))] use crate::error::Error; @@ -303,11 +305,18 @@ impl DriveDocumentHavingQuery<'_> { /// tree(s). See /// [`DriveDocumentRankedQuery::indexed_property_name_tree_path`](super::drive_document_ranked_query::DriveDocumentRankedQuery::indexed_property_name_tree_path). pub fn indexed_property_name_tree_path(&self, branch: usize) -> Result>, Error> { + let prefix_values = + self.prefix_branches + .get(branch) + .ok_or(Error::Drive(DriveError::NotSupported( + "ranked and having-range queries addressed a prefix branch outside the \ + query's resolved branch set", + )))?; indexed_property_name_tree_path_for_index( &self.contract_id, &self.document_type_name, self.index, - &self.prefix_branches[branch], + prefix_values, ) } } diff --git a/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs b/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs index 0d20e3cb2e4..e690a4ab5f9 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/mode_detection/v0/mod.rs @@ -31,9 +31,9 @@ use grovedb::element::indexed::AVG_FIXED_POINT_SCALE; /// with no `OFFSET`, no `START AT` / `START AFTER`, exactly one /// `GROUP BY` property, `WHERE` clauses (when present) that pin the /// covering compound ranked index's leading properties — one clause per -/// property, each an equality, at most one of them an `IN` whose -/// elements fan the bound out across one prefix branch per element -/// (merged deterministically; see the ranked surface's +/// property, each an equality except that **at most one** clause may be +/// an `IN` whose elements fan the bound out across one prefix branch +/// per element (merged deterministically; see the ranked surface's /// `prefix_pins_from_where_clauses`) — exactly one `HAVING` clause whose aggregate /// **is the selected aggregate** (same function, same field), an operator /// from the contiguous-range family (`=`, `>`, `>=`, `<`, `<=`, and the diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs b/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs index 253f866db65..4a1b1ed4a0d 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/branches.rs @@ -1,20 +1,23 @@ //! Branch mechanics for `IN`-pinned ranked / having-range queries — //! shared by the executors (walk one secondary per branch, merge) and -//! the verifiers (verify one proof per branch, re-merge), so both sides -//! implement one comparator and one proof-container layout. +//! the verifiers (verify one branched envelope, re-merge), so both +//! sides implement one comparator and one grove-path decomposition. //! //! ## Why a merge needs no proof of its own //! -//! Each branch's walk is independently proved complete against the same -//! root hash, and the merged page is a *deterministic function* of the -//! branch pages: any union entry that precedes a returned entry in the -//! merge order is preceded, within its own branch, by fewer than `limit` +//! Each branch's walk is proved complete inside one grovedb **branched +//! envelope** (shared ancestor layers once, one multi-key proof at the +//! branching level, one secondary proof per branch, one root hash), +//! and the merged page is a *deterministic function* of the branch +//! pages: any union entry that precedes a returned entry in the merge +//! order is preceded, within its own branch, by fewer than `limit` //! entries — so it is in its branch's returned page. The union's first //! `limit` entries are therefore contained in the union of the branch -//! pages, and re-merging verified branch pages reconstructs a complete, -//! correctly ordered page. (This is the same argument for both surfaces: -//! "first `limit` in merge order restricted to the branch" is top-k for -//! ranked and the in-bound range prefix for having.) +//! pages, and re-merging verified branch pages reconstructs a +//! complete, correctly ordered page. (This is the same argument for +//! both surfaces: "first `limit` in merge order restricted to the +//! branch" is top-k for ranked and the in-bound range prefix for +//! having.) //! //! ## The merge order //! @@ -25,16 +28,12 @@ //! element order — which also makes `null` (the empty segment) sort //! first deterministically. -use super::{RankedEntry, RankedEntryValue}; +use super::{RankedAxis, RankedEntry, RankedEntryValue}; use crate::error::drive::DriveError; use crate::error::Error; +use grovedb::operations::proof::indexed_axis::AxisEntries; use std::cmp::Ordering; -/// Version byte of the branch-proof container. Bumped only with a -/// method-version bump on the prove/verify pair — the container is part -/// of the prover/verifier agreement, not a transport detail. -const BRANCH_PROOF_CONTAINER_VERSION: u8 = 1; - /// The position (index into a branch's segment list) at which the /// branches differ — the `IN` pin's position in the covering index's /// leading properties. `None` when there is a single branch (no `IN`), @@ -127,68 +126,89 @@ pub fn merge_branch_pages( Ok(merged) } -/// Frame per-branch grovedb proofs into the single opaque byte string -/// the wire's `Proof` carries: version byte, `u16` branch count, then -/// each proof length-prefixed with a `u32` (all big-endian). Used only -/// when there are two or more branches — a single-branch proof stays -/// the raw grovedb envelope, byte-identical to the pre-`IN` surface. -pub fn encode_branch_proofs(proofs: &[Vec]) -> Vec { - let mut out = Vec::with_capacity(3 + proofs.iter().map(|p| 4 + p.len()).sum::()); - out.push(BRANCH_PROOF_CONTAINER_VERSION); - out.extend_from_slice(&(proofs.len() as u16).to_be_bytes()); - for proof in proofs { - out.extend_from_slice(&(proof.len() as u32).to_be_bytes()); - out.extend_from_slice(proof); - } - out -} - -/// Parse the branch-proof container, requiring exactly -/// `expected_branches` proofs — the verifier derives that count from -/// its own resolution of the request, so a server cannot drop or -/// duplicate a branch without the container failing to parse. Trailing -/// bytes are rejected: an envelope is exactly its declared content. -pub fn decode_branch_proofs(bytes: &[u8], expected_branches: usize) -> Result>, Error> { - let malformed = |what: &str| { - Error::Drive(DriveError::CorruptedDriveState(format!( - "branch-proof container: {what}" - ))) - }; - let (&version, mut rest) = bytes.split_first().ok_or_else(|| malformed("empty"))?; - if version != BRANCH_PROOF_CONTAINER_VERSION { - return Err(malformed(&format!( - "unknown container version {version}; expected {BRANCH_PROOF_CONTAINER_VERSION}" - ))); - } - if rest.len() < 2 { - return Err(malformed("truncated branch count")); - } - let (count_bytes, tail) = rest.split_at(2); - let count = u16::from_be_bytes([count_bytes[0], count_bytes[1]]) as usize; - rest = tail; - if count != expected_branches { - return Err(malformed(&format!( - "container carries {count} branch proofs; the request resolves to \ - {expected_branches} branches" - ))); - } - let mut proofs = Vec::with_capacity(count); - for _ in 0..count { - if rest.len() < 4 { - return Err(malformed("truncated proof length")); +/// Decompose per-branch grove paths into the `(shared prefix, branch +/// keys, shared suffix)` triple grovedb's branched proof primitives +/// take. The paths differ at exactly one segment position by +/// construction (one `IN` pin); anything else is an internal +/// resolution error. +pub fn decompose_branch_paths( + paths: &[Vec>], +) -> Result<(Vec>, Vec>, Vec>), Error> { + let first = paths.first().ok_or_else(|| { + Error::Drive(DriveError::CorruptedDriveState( + "branch decomposition over zero paths".to_string(), + )) + })?; + let mut varying: Option = None; + for other in &paths[1..] { + if other.len() != first.len() { + return Err(Error::Drive(DriveError::CorruptedDriveState( + "branch paths of different lengths".to_string(), + ))); } - let (len_bytes, tail) = rest.split_at(4); - let len = - u32::from_be_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize; - if tail.len() < len { - return Err(malformed("truncated proof body")); + for (position, (a, b)) in first.iter().zip(other.iter()).enumerate() { + if a != b { + match varying { + None => varying = Some(position), + Some(existing) if existing == position => {} + Some(_) => { + return Err(Error::Drive(DriveError::CorruptedDriveState( + "branch paths differ at more than one segment".to_string(), + ))); + } + } + } } - let (proof, tail) = tail.split_at(len); - proofs.push(proof.to_vec()); - rest = tail; } - if !rest.is_empty() { - return Err(malformed("trailing bytes after the declared proofs")); + let position = varying.ok_or_else(|| { + Error::Drive(DriveError::CorruptedDriveState( + "branch paths are identical; the encoder rejects duplicate branches".to_string(), + )) + })?; + let prefix = first[..position].to_vec(); + let keys = paths + .iter() + .map(|path| path[position].clone()) + .collect::>(); + let suffix = first[position + 1..].to_vec(); + Ok((prefix, keys, suffix)) +} + +/// Translate one branch's verified [`AxisEntries`] into drive entries +/// on the requested axis — the same mapping the single-path verifiers +/// perform, shared here so both surfaces' branched verifiers agree. +pub fn axis_entries_to_ranked( + axis: RankedAxis, + entries: AxisEntries, +) -> Result, Error> { + match (axis, entries) { + (RankedAxis::Count, AxisEntries::Count(entries)) => Ok(entries + .into_iter() + .map(|(count, key)| RankedEntry { + in_key: None, + key, + value: RankedEntryValue::Count(count), + }) + .collect()), + (RankedAxis::Sum, AxisEntries::Sum(entries)) => Ok(entries + .into_iter() + .map(|(sum, key)| RankedEntry { + in_key: None, + key, + value: RankedEntryValue::Sum(sum), + }) + .collect()), + (RankedAxis::Avg, AxisEntries::Avg(entries)) => Ok(entries + .into_iter() + .map(|(avg, key)| RankedEntry { + in_key: None, + key, + value: RankedEntryValue::AvgFixedPoint(avg), + }) + .collect()), + (axis, other) => Err(Error::Drive(DriveError::CorruptedDriveState(format!( + "a branch of a {axis:?} proof verified to {} entries of a different axis shape", + other.len() + )))), } - Ok(proofs) } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs index 53f62a064d1..78b5e586538 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs @@ -10,7 +10,7 @@ //! Whole module is gated `feature = "server"` via the parent's //! `pub mod execute_top_k;` declaration. -use super::branches::{encode_branch_proofs, merge_branch_pages}; +use super::branches::{decompose_branch_paths, merge_branch_pages}; use super::{DriveDocumentRankedQuery, RankedAxis, RankedEntry, RankedEntryValue, RankedPage}; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -219,21 +219,32 @@ impl DriveDocumentRankedQuery<'_> { platform_version: &PlatformVersion, ) -> Result, Error> { if self.prefix_branches.len() > 1 { - // One indexed-axis proof per branch, framed into the - // versioned container in canonical branch order. The - // verifier re-derives the branch set from the request, so a - // dropped, duplicated, or reordered branch fails there. - let proofs = (0..self.prefix_branches.len()) - .map(|branch| { - self.execute_top_k_with_proof_branch( - branch, - drive, - transaction, - platform_version, - ) - }) + // One grovedb **branched** envelope: shared ancestor layers + // once, one multi-key proof at the branching level, one + // secondary proof per branch — a single proof with a single + // root hash. The verifier re-derives the branch set from + // the request, so a dropped, duplicated, or reordered + // branch fails there. + let grove_version = &platform_version.drive.grove_version; + let paths = (0..self.prefix_branches.len()) + .map(|branch| self.indexed_property_name_tree_path(branch)) .collect::, Error>>()?; - return Ok(encode_branch_proofs(&proofs)); + let (prefix, keys, suffix) = decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let suffix_refs: Vec<&[u8]> = suffix.iter().map(|s| s.as_slice()).collect(); + let CostContext { value, cost: _ } = + drive.grove.prove_indexed_axis_top_k_paginated_branched( + &prefix_refs, + &keys, + &suffix_refs, + self.axis.into(), + self.k, + self.offset as u64, + self.descending, + transaction, + grove_version, + ); + return value.map_err(|e| Error::GroveDB(Box::new(e))); } self.execute_top_k_with_proof_branch(0, drive, transaction, platform_version) } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs index 63cc322e45b..eb0ddcc0ade 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/index_picker.rs @@ -196,7 +196,7 @@ pub fn no_covering_index_message( } else { format!( "a compound index on [{}, {group_by_property}] (every leading property pinned \ - by an equality `where` clause, the trailing property grouped over)", + by an equality or `IN` `where` clause, the trailing property grouped over)", pin_fields() ) }; @@ -206,7 +206,7 @@ pub fn no_covering_index_message( if prefix_pins.is_empty() { String::new() } else { - format!(" with equality pins on [{}]", pin_fields()) + format!(" with pins on [{}]", pin_fields()) }, axis.required_index_keyword(), if aggregate_field.is_empty() { @@ -301,6 +301,34 @@ pub fn encode_prefix_branches( }) .collect::, Error>>()?; + // Defense in depth at the shared choke point: the grammar enforces + // both invariants upstream, but this function is `pub` and the + // prover/verifier agreement hangs off it, so a mis-built pin set + // must fail here rather than collapse to zero branches (a + // downstream panic) or fan out into an unbounded cartesian product + // (which would also break the one-varying-position assumption + // `in_key` and the merge order rely on). + if per_property.iter().any(|candidates| candidates.is_empty()) { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "internal resolution mismatch: a prefix pin carries no values", + ), + )); + } + if per_property + .iter() + .filter(|candidates| candidates.len() > 1) + .count() + > 1 + { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "internal resolution mismatch: more than one branching pin — the grammar \ + admits at most one `IN` across the prefix properties", + ), + )); + } + // The grammar admits at most one multi-value pin, so this product // is |IN| branches (or exactly one), already in canonical order // because the only varying position was sorted above. diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/path.rs b/packages/rs-drive/src/query/drive_document_ranked_query/path.rs index ec737825776..ddb5380d79c 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/path.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/path.rs @@ -24,7 +24,7 @@ use dpp::data_contract::document_type::Index; /// tree. See [`DriveDocumentRankedQuery::indexed_property_name_tree_path`] /// for the segment layout. /// -/// `equality_prefix_values` carries the **encoded index-key bytes** of +/// The branch's prefix segments carry the **encoded index-key bytes** of /// each leading property's pinned value, in index-property order — one /// per property before the terminal one. Empty for a single-property /// index. The arity must match exactly: a compound index's terminal @@ -84,7 +84,7 @@ impl DriveDocumentRankedQuery<'_> { /// For a compound index `[p1, …, pn]`, each leading property /// contributes two segments — its name and the **encoded index-key /// bytes of its pinned value** (from - /// [`Self::equality_prefix_values`]) — and the terminal property + /// [`Self::prefix_branches`]) — and the terminal property /// name closes the path: /// /// ```text @@ -105,11 +105,18 @@ impl DriveDocumentRankedQuery<'_> { /// `branch` indexes into [`Self::prefix_branches`]; single-branch /// queries (no `IN` pin) always pass `0`. pub fn indexed_property_name_tree_path(&self, branch: usize) -> Result>, Error> { + let prefix_values = + self.prefix_branches + .get(branch) + .ok_or(Error::Drive(DriveError::NotSupported( + "ranked and having-range queries addressed a prefix branch outside the \ + query's resolved branch set", + )))?; indexed_property_name_tree_path_for_index( &self.contract_id, &self.document_type_name, self.index, - &self.prefix_branches[branch], + prefix_values, ) } } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs index 0d1fdac7598..964c01228b0 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs @@ -2641,12 +2641,15 @@ mod pinned_prefix { ); } - /// The tamper matrix on the branch container: a response whose - /// branch proofs are reordered, dropped, duplicated, re-versioned, - /// or padded must fail verification — never silently reorder or - /// shrink the merged page. + /// Platform-level tamper cases on the branched envelope. The deep + /// matrix — reordered branch keys, duplicated or dropped branch + /// tails, echo mismatches — is pinned in grovedb's + /// `indexed_axis_branched_proof_tests`, since the envelope is one + /// grovedb proof now; here we pin what the platform layer itself + /// must not confuse: corrupted bytes, and the single-branch / + /// multi-branch envelope shapes never cross-verifying. #[test] - fn tampered_branch_containers_do_not_verify() { + fn tampered_or_mismatched_branched_proofs_do_not_verify() { let (drive, contract) = setup_grades_compound_ranked(); insert_grades( &drive, @@ -2663,76 +2666,48 @@ mod pinned_prefix { // Baseline sanity: untampered verifies. query .verify_ranked_top_k_proof(&proof, platform_version()) - .expect("untampered container verifies"); - - // Decompose the container by hand: [version][u16 count]([u32 len][bytes])* - assert_eq!(proof[0], 1, "container version byte"); - let count = u16::from_be_bytes([proof[1], proof[2]]) as usize; - assert_eq!(count, 2); - let mut branch_proofs = Vec::new(); - let mut rest = &proof[3..]; - for _ in 0..count { - let len = u32::from_be_bytes([rest[0], rest[1], rest[2], rest[3]]) as usize; - branch_proofs.push(rest[4..4 + len].to_vec()); - rest = &rest[4 + len..]; - } - let reframe = |proofs: &[Vec]| { - let mut out = vec![1u8]; - out.extend_from_slice(&(proofs.len() as u16).to_be_bytes()); - for p in proofs { - out.extend_from_slice(&(p.len() as u32).to_be_bytes()); - out.extend_from_slice(p); - } - out - }; - - // Reordered: branch 0's proof is verified against branch 1's - // path and fails inside grovedb. - let reordered = reframe(&[branch_proofs[1].clone(), branch_proofs[0].clone()]); - assert!( - query - .verify_ranked_top_k_proof(&reordered, platform_version()) - .is_err(), - "reordered branch proofs must not verify" - ); + .expect("untampered branched envelope verifies"); - // Dropped: count mismatch against the query's own resolution. - let dropped = reframe(&[branch_proofs[0].clone()]); + // Corrupted bytes. + let mut corrupted = proof.clone(); + let mid = corrupted.len() / 2; + corrupted[mid] ^= 0xFF; assert!( query - .verify_ranked_top_k_proof(&dropped, platform_version()) + .verify_ranked_top_k_proof(&corrupted, platform_version()) .is_err(), - "a dropped branch must not verify" + "a flipped byte must not verify" ); - // Duplicated: same count, but branch 1's slot holds branch 0's - // proof — wrong path again. - let duplicated = reframe(&[branch_proofs[0].clone(), branch_proofs[0].clone()]); + // Truncated bytes. + let truncated = &proof[..proof.len() - 8]; assert!( query - .verify_ranked_top_k_proof(&duplicated, platform_version()) + .verify_ranked_top_k_proof(truncated, platform_version()) .is_err(), - "a duplicated branch proof must not verify" + "a truncated envelope must not verify" ); - // Unknown container version. - let mut reversioned = proof.clone(); - reversioned[0] = 2; + // A single-pin proof must not verify under the branched query, + // nor a branched proof under a single-pin query — the two + // envelope shapes are distinct grovedb types. + let single = pin(IDENTITY_X); + let single_proof = match run(&drive, &contract, &single, 2, true).expect("prove") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof"), + }; assert!( query - .verify_ranked_top_k_proof(&reversioned, platform_version()) + .verify_ranked_top_k_proof(&single_proof, platform_version()) .is_err(), - "an unknown container version must not verify" + "a single-branch envelope must not verify under an IN query" ); - - // Trailing bytes after the declared proofs. - let mut padded = proof.clone(); - padded.push(0); + let single_query = client_side_query(&contract, &single, 2); assert!( - query - .verify_ranked_top_k_proof(&padded, platform_version()) + single_query + .verify_ranked_top_k_proof(&proof, platform_version()) .is_err(), - "trailing bytes must not verify" + "a branched envelope must not verify under a single-pin query" ); } diff --git a/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs index 3cde3cfb2b9..a5c94039ed6 100644 --- a/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document_having/verify_having_range_proof/v0/mod.rs @@ -1,7 +1,7 @@ use crate::error::drive::DriveError; use crate::error::Error; use crate::query::drive_document_ranked_query::branches::{ - decode_branch_proofs, merge_branch_pages, + axis_entries_to_ranked, decompose_branch_paths, merge_branch_pages, }; use crate::query::{DriveDocumentHavingQuery, RankedAxis, RankedEntry, RankedEntryValue}; use crate::verify::RootHash; @@ -45,41 +45,51 @@ impl DriveDocumentHavingQuery<'_> { proof: &[u8], ) -> Result<(RootHash, Vec), Error> { if self.prefix_branches.len() > 1 { - // `IN`-pinned request: same branch-container discipline as - // the ranked verifier — count from this query's own - // resolution, one root hash across branches, page re-derived - // by the shared merge. - let branch_proofs = decode_branch_proofs(proof, self.prefix_branches.len())?; - let mut root_hash: Option = None; - let mut per_branch = Vec::with_capacity(branch_proofs.len()); - for (branch, branch_proof) in branch_proofs.iter().enumerate() { - let (branch_root, entries) = - self.verify_having_range_proof_v0_branch(branch, branch_proof)?; - match root_hash { - None => root_hash = Some(branch_root), - Some(existing) if existing == branch_root => {} - Some(_) => { - return Err(Error::Drive(DriveError::CorruptedDriveState( - "branch proofs attest different root hashes: every branch of \ - one response must be proved against one platform state" - .to_string(), - ))); + // `IN`-pinned request: one grovedb branched envelope — same + // discipline as the ranked verifier (branch set from this + // query's own resolution, tails bound to keys by the + // branching-level proof, one root hash, page re-derived by + // the shared merge). + let paths = (0..self.prefix_branches.len()) + .map(|branch| self.indexed_property_name_tree_path(branch)) + .collect::, Error>>()?; + let (prefix, keys, suffix) = decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let suffix_refs: Vec<&[u8]> = suffix.iter().map(|s| s.as_slice()).collect(); + let axis = self.bounds.axis(); + let result = grovedb::GroveDb::verify_indexed_axis_query_branched( + proof, + &prefix_refs, + &keys, + &suffix_refs, + axis.into(), + self.bounds.merk_query(self.descending), + Some(self.limit), + ) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + let per_branch = result + .branches + .into_iter() + .map(|entries| { + let entries = axis_entries_to_ranked(axis, entries)?; + if entries.len() > self.limit as usize { + return Err(Error::Drive(DriveError::CorruptedDriveState(format!( + "a branch of a having range proof verified to {} entries for \ + limit = {}", + entries.len(), + self.limit + )))); } - } - per_branch.push(entries); - } + Ok(entries) + }) + .collect::, Error>>()?; let entries = merge_branch_pages( per_branch, &self.prefix_branches, self.descending, self.limit as usize, )?; - let root_hash = root_hash.ok_or_else(|| { - Error::Drive(DriveError::CorruptedDriveState( - "branch container verified to zero branches".to_string(), - )) - })?; - return Ok((root_hash, entries)); + return Ok((result.root_hash, entries)); } self.verify_having_range_proof_v0_branch(0, proof) } diff --git a/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs index 7eb74a39585..5e446370227 100644 --- a/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document_ranked/verify_ranked_top_k_proof/v0/mod.rs @@ -1,7 +1,7 @@ use crate::error::drive::DriveError; use crate::error::Error; use crate::query::drive_document_ranked_query::branches::{ - decode_branch_proofs, merge_branch_pages, + axis_entries_to_ranked, decompose_branch_paths, merge_branch_pages, }; use crate::query::{ DriveDocumentRankedQuery, RankedAxis, RankedEntry, RankedEntryValue, RankedPage, @@ -57,46 +57,55 @@ impl DriveDocumentRankedQuery<'_> { proof: &[u8], ) -> Result<(RootHash, RankedPage), Error> { if self.prefix_branches.len() > 1 { - // `IN`-pinned request: the proof bytes are the branch - // container. The branch count comes from *this* query's own - // resolution, so a container with a dropped, duplicated, or - // added branch fails to parse; a reordered or substituted - // branch proof fails its branch's own path verification; and - // all branches must attest one root hash. The page is then - // re-derived by the shared merge — the client never trusts a - // server-side merge. - let branch_proofs = decode_branch_proofs(proof, self.prefix_branches.len())?; - let mut root_hash: Option = None; - let mut per_branch = Vec::with_capacity(branch_proofs.len()); - for (branch, branch_proof) in branch_proofs.iter().enumerate() { - let (branch_root, page) = - self.verify_ranked_top_k_proof_v0_branch(branch, branch_proof)?; - match root_hash { - None => root_hash = Some(branch_root), - Some(existing) if existing == branch_root => {} - Some(_) => { - return Err(Error::Drive(DriveError::CorruptedDriveState( - "branch proofs attest different root hashes: every branch of \ - one response must be proved against one platform state" - .to_string(), - ))); + // `IN`-pinned request: the proof is one grovedb branched + // envelope. The branch set (and its order) comes from + // *this* query's own resolution; grovedb binds each branch + // tail to its branch key through the branching-level + // multi-key proof, reconstructs one root hash, and echoes + // `(axis, k, offset, direction)`. The page is then + // re-derived by the shared merge — the client never trusts + // a server-side merge. + let paths = (0..self.prefix_branches.len()) + .map(|branch| self.indexed_property_name_tree_path(branch)) + .collect::, Error>>()?; + let (prefix, keys, suffix) = decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let suffix_refs: Vec<&[u8]> = suffix.iter().map(|s| s.as_slice()).collect(); + let result = grovedb::GroveDb::verify_indexed_axis_top_k_paginated_branched( + proof, + &prefix_refs, + &keys, + &suffix_refs, + self.axis.into(), + self.k, + self.offset as u64, + self.descending, + ) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + let per_branch = result + .branches + .into_iter() + .map(|(_skipped, entries)| { + let entries = axis_entries_to_ranked(self.axis, entries)?; + if entries.len() > self.k as usize { + return Err(Error::Drive(DriveError::CorruptedDriveState(format!( + "a branch of a ranked top-k proof verified to {} entries for \ + k = {}", + entries.len(), + self.k + )))); } - } - per_branch.push(page.entries); - } + Ok(entries) + }) + .collect::, Error>>()?; let entries = merge_branch_pages( per_branch, &self.prefix_branches, self.descending, self.k as usize, )?; - let root_hash = root_hash.ok_or_else(|| { - Error::Drive(DriveError::CorruptedDriveState( - "branch container verified to zero branches".to_string(), - )) - })?; return Ok(( - root_hash, + result.root_hash, RankedPage { skipped: 0, entries, diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index 27742bc04de..c0dc25e228c 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" thiserror = { version = "2.0.12" } bincode = { version = "=2.0.1" } versioned-feature-core = { git = "https://github.com/dashpay/versioned-feature-core", version = "1.0.0" } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } [features] mock-versions = [] diff --git a/packages/rs-platform-wallet/Cargo.toml b/packages/rs-platform-wallet/Cargo.toml index 7d404f6985a..d6b59f25ac6 100644 --- a/packages/rs-platform-wallet/Cargo.toml +++ b/packages/rs-platform-wallet/Cargo.toml @@ -69,7 +69,7 @@ zeroize = "1" log = "0.4" # Shielded pool (optional, behind `shielded` feature) -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } # Direct `rusqlite` access so `FileBackedShieldedStore::open_path` can set # WAL + synchronous=NORMAL pragmas before handing the connection to # `ClientPersistentCommitmentTree`. Version locked to match the rev grovedb diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 8f8ba61d9df..cb90a8b234a 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -18,7 +18,7 @@ drive = { path = "../rs-drive", default-features = false, features = [ ] } drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a2791bbdca756d6a6113024aec48f09f7a33faa9", features = [ +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", features = [ "client", "sqlite", ], optional = true } From 44f23fc11bf364fc9410754cad0b93c0cc4cff0c Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 14 Aug 2026 01:47:18 +0700 Subject: [PATCH 5/5] fix(drive)!: an absent IN element contributes an empty branch, not an error prefix IN [existing, absent] previously aborted the whole request the moment any selected prefix had no documents, losing the existing branches' valid results - the advertised union semantics were incomplete. Now an element whose prefix subtree was never created contributes the empty page on both execution paths: - Proved: grovedb's branched envelope authenticates the absence at the branching level (the exact-key multi-key proof proves both presence and absence), carries no tail for the absent branch, and rejects absence forgery in both directions - claiming a present key absent or grafting a tail onto an absent key both fail verification. - Unproved: the executors check the branch key at the branching Merk and treat a missing key as the empty branch, so proved and unproved execution stay equivalent. Presence is decided at the branching Merk itself: deeper breakage under a present key stays an error, and the single-==-pin contract is untouched (an unknown pinned value still errors rather than fabricating an empty page; its test still pins that). grovedb pin bumped to the absence-aware revision; round-trip coverage on both surfaces via never-written IN elements. Co-Authored-By: Claude Fable 5 --- Cargo.lock | 44 +++++++++--------- book/src/drive/document-ranked-trees.md | 2 +- .../protos/platform/v0/platform.proto | 4 +- packages/rs-dpp/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 8 ++-- packages/rs-drive/Cargo.toml | 12 ++--- .../execute_range.rs | 31 +++++++++++++ .../drive_document_having_query/tests.rs | 33 ++++++++++++++ .../execute_top_k.rs | 43 ++++++++++++++++-- .../drive_document_ranked_query/tests.rs | 45 +++++++++++++++++++ packages/rs-platform-version/Cargo.toml | 2 +- packages/rs-platform-wallet/Cargo.toml | 2 +- packages/rs-sdk/Cargo.toml | 2 +- 13 files changed, 188 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76f2992e59c..58b4ca99fd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,7 +576,7 @@ dependencies = [ "bitflags 2.13.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -2955,7 +2955,7 @@ dependencies = [ [[package]] name = "grovedb" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "axum 0.8.9", "bincode", @@ -2993,7 +2993,7 @@ dependencies = [ [[package]] name = "grovedb-bulk-append-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "blake3", @@ -3009,7 +3009,7 @@ dependencies = [ [[package]] name = "grovedb-commitment-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3025,7 +3025,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "integer-encoding", "intmap", @@ -3035,7 +3035,7 @@ dependencies = [ [[package]] name = "grovedb-dense-fixed-sized-merkle-tree" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "blake3", @@ -3048,7 +3048,7 @@ dependencies = [ [[package]] name = "grovedb-element" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "bincode_derive", @@ -3063,7 +3063,7 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "grovedb-costs", "hex", @@ -3075,7 +3075,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "bincode_derive", @@ -3101,7 +3101,7 @@ dependencies = [ [[package]] name = "grovedb-merkle-mountain-range" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "blake3", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "grovedb-path" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "hex", ] @@ -3120,7 +3120,7 @@ dependencies = [ [[package]] name = "grovedb-query" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "bincode", "byteorder", @@ -3136,7 +3136,7 @@ dependencies = [ [[package]] name = "grovedb-storage" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "blake3", "grovedb-costs", @@ -3155,7 +3155,7 @@ dependencies = [ [[package]] name = "grovedb-version" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "thiserror 2.0.18", "versioned-feature-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3164,7 +3164,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "hex", "itertools 0.14.0", @@ -3173,7 +3173,7 @@ dependencies = [ [[package]] name = "grovedbg-types" version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=dd2004e4eb0643a081356c0468132026217d7d66#dd2004e4eb0643a081356c0468132026217d7d66" +source = "git+https://github.com/dashpay/grovedb?rev=1d07f587a33b8e2a131c483f0c889ce7ab585864#1d07f587a33b8e2a131c483f0c889ce7ab585864" dependencies = [ "serde", "serde_with 3.21.0", @@ -3589,7 +3589,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.4", "system-configuration", "tokio", "tower-service", @@ -5542,7 +5542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.13.0", "log", "multimap", "petgraph", @@ -5563,7 +5563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5576,7 +5576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5712,7 +5712,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.2", "rustls", - "socket2 0.5.10", + "socket2 0.6.4", "thiserror 2.0.18", "tokio", "tracing", @@ -5750,7 +5750,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.4", "tracing", "windows-sys 0.59.0", ] diff --git a/book/src/drive/document-ranked-trees.md b/book/src/drive/document-ranked-trees.md index 85cc2d34c8e..9dde105d7bc 100644 --- a/book/src/drive/document-ranked-trees.md +++ b/book/src/drive/document-ranked-trees.md @@ -341,7 +341,7 @@ Note that the fixture puts each shape on its **own document type**. That's not a | Top / bottom K groups by sum of a property | `rankedSummable: true` on an index with `summable: ""` + `rangeSummable: true` | | Top / bottom K groups by average of a property | `rankedAverageable: true` on an index with `averageable: ""` + `rangeAverageable: true` (or the count+sum longhand) | | Two rankings on one index (e.g. by count *and* by average) | Both keywords. The tree is a PCPSIT carrying both axes in its TLV; you pay one secondary Merk per axis on every write. | -| A ranking filtered by another property (`top 5 restaurants in London`) | A **compound ranked index** with the filter property leading: `[city, restaurantId]` with the ranked flags. Each city gets its own secondary; the query pins the prefix with an equality `where` (`WHERE city == "London" GROUP BY restaurantId ORDER BY DESC LIMIT 5`). Equality pins select one prefix; at most one pin may be an `IN` (2..=10 distinct elements, `null` legal for the absent-value prefix), which walks one secondary per element and merges by `(aggregate, encoded prefix, group key)` with per-branch proofs in one container — entries then carry `in_key`. A range operator on the prefix stays rejected, `OFFSET` is rejected together with `IN`, and there is still no global cross-prefix ordering beyond that merge. | +| A ranking filtered by another property (`top 5 restaurants in London`) | A **compound ranked index** with the filter property leading: `[city, restaurantId]` with the ranked flags. Each city gets its own secondary; the query pins the prefix with an equality `where` (`WHERE city == "London" GROUP BY restaurantId ORDER BY DESC LIMIT 5`). Equality pins select one prefix; at most one pin may be an `IN` (2..=10 distinct elements, `null` legal for the absent-value prefix, and a never-written element contributes an empty branch), which walks one secondary per element and merges by `(aggregate, encoded prefix, group key)` with per-branch proofs in one container — entries then carry `in_key`. A range operator on the prefix stays rejected, `OFFSET` is rejected together with `IN`, and there is still no global cross-prefix ordering beyond that merge. | | A ranking on a unique or contested index | Not available, and not meaningful: every group holds at most one document. | | Range aggregates without ranking (the 4.0 surface) | Just the `range*` flags. Ranking is strictly additive — adding it never changes what a range query returns. | | Nothing ranking-aware (default) | Don't set any `ranked*` flag. The terminal property-name tree keeps the type its range flags give it. | diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index c3bfe87aba5..573086f3b98 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -893,11 +893,11 @@ message GetDocumentsRequest { // - a is the In field AND b is the range field, in that order → existing compound distinct shape; entries carry both `in_key` (= a's value) and `key` (= b's value). // // `select=, group_by=[p], order_by=[]` (protocol v14+) — **ranked mode**: - // - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned (one clause per property, `group_by` names the trailing property) — `EQUAL` pins one prefix, and **at most one** clause may be `IN` (2..=10 distinct elements, `null` legal), fanning the walk out across one prefix branch per element and merging by `(aggregate, encoded prefix, group key)`; merged entries carry `in_key`. `offset` is rejected together with `IN` (rank-skip is per-secondary). + // - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned (one clause per property, `group_by` names the trailing property) — `EQUAL` pins one prefix, and **at most one** clause may be `IN` (2..=10 distinct elements, `null` legal; an element whose prefix was never written contributes an empty branch — union semantics), fanning the walk out across one prefix branch per element and merging by `(aggregate, encoded prefix, group key)`; merged entries carry `in_key`. `offset` is rejected together with `IN` (rank-skip is per-secondary). // - `DESC` is the "top n" reading (walk the axis from the largest aggregate down), `ASC` the "bottom n" reading. Worked example: `SELECT AVG(grade) GROUP BY restaurantId ORDER BY grade DESC LIMIT 1 OFFSET 4` is the 5th-best restaurant. // // `select=, group_by=[p], having=[ ]` (protocol v14+) — **having-range mode**: - // - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one pin per leading index property on a compound ranked index, at most one of them an `IN` (2..=10 distinct elements) that fans the bound out across prefix branches and merges, entries carrying `in_key`. + // - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one pin per leading index property on a compound ranked index, at most one of them an `IN` (2..=10 distinct elements; a never-written element contributes an empty branch) that fans the bound out across prefix branches and merges, entries carrying `in_key`. // - no offset or cursor pagination: a page cut at `limit` continues only by tightening the bound past the last *distinct* aggregate value seen; a cut inside a tie (several groups sharing the boundary aggregate) cannot be continued, so size `limit` above the widest expected tie. // // **Rejected shapes** (return `Unsupported`): diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index eae4dabe34b..abed6debe4c 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -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 = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", optional = true } [dev-dependencies] tokio = { version = "1.40", features = ["full"] } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index aaa5827ed34..429826a990b 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -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 = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } nonempty = "0.11" # Shielded-pool snapshot needs raw RocksDB SstFileWriter + ingest_external_file_cf # bindings, and blake3 for the snapshot-file checksum. @@ -107,7 +107,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 = "dd2004e4eb0643a081356c0468132026217d7d66", features = ["client"] } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", features = ["client"] } assert_matches = "1.5.0" drive-abci = { path = ".", features = ["testing-config", "mocks", "shielded_test_data"] } bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f" } @@ -121,8 +121,8 @@ integer-encoding = { version = "4.0.0" } # For dump_only_default_and_aux_cfs_under_shielded_subtree_prefix — same # subtree-prefix algorithm grovedb uses internally. -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } [features] default = ["bls-signatures"] diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index c2278c8f482..ea463f4378a 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -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 = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true, default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", optional = true, default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", optional = true } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", optional = true } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } [dev-dependencies] criterion = "0.5" diff --git a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs index d6f7d8d0295..93cc32ed61d 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/execute_range.rs @@ -48,6 +48,12 @@ impl DriveDocumentHavingQuery<'_> { // prefix), merged with the shared comparator. let per_branch = (0..self.prefix_branches.len()) .map(|branch| { + // Absent element = empty branch; same union + // semantics as the ranked surface and the proved + // path's authenticated absence. + if self.branch_is_absent(branch, drive, transaction, platform_version)? { + return Ok(Vec::new()); + } self.execute_range_no_proof_branch(branch, drive, transaction, platform_version) }) .collect::, Error>>()?; @@ -61,6 +67,31 @@ impl DriveDocumentHavingQuery<'_> { self.execute_range_no_proof_branch(0, drive, transaction, platform_version) } + /// Whether this branch's key is absent at the branching Merk — see + /// the ranked sibling for the contract. + pub(crate) fn branch_is_absent( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let grove_version = &platform_version.drive.grove_version; + let paths = (0..self.prefix_branches.len()) + .map(|b| self.indexed_property_name_tree_path(b)) + .collect::, Error>>()?; + let (prefix, keys, _suffix) = + super::super::drive_document_ranked_query::branches::decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let CostContext { value, cost: _ } = drive.grove.get_raw_optional( + prefix_refs.as_slice().into(), + &keys[branch], + transaction, + grove_version, + ); + Ok(value.map_err(|e| Error::GroveDB(Box::new(e)))?.is_none()) + } + /// One branch's in-bound page — the entire pre-`IN` executor, /// parameterized by which prefix branch's terminal tree it walks. fn execute_range_no_proof_branch( diff --git a/packages/rs-drive/src/query/drive_document_having_query/tests.rs b/packages/rs-drive/src/query/drive_document_having_query/tests.rs index 3904bebe0a4..17e086c2197 100644 --- a/packages/rs-drive/src/query/drive_document_having_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_having_query/tests.rs @@ -2296,4 +2296,37 @@ mod pinned_prefix { .expect("root hash must be readable"), ); } + + /// The having sibling of the ranked surface's absent-element test: + /// `identityId IN [X, never-written]` bounds X's groups and treats + /// the absent branch as empty, on both the read and the proved + /// path. + #[test] + fn an_absent_in_element_contributes_an_empty_branch() { + let (drive, contract) = setup_grades_compound_ranked(); + insert_grades(&drive, &contract, 3000, &[(IDENTITY_X, "art", 90)]); + + let never_written = [9u8; 32]; + let pins = vec![WhereClause { + field: PREFIX_PROPERTY.to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::Identifier(IDENTITY_X), + Value::Identifier(never_written), + ]), + }]; + let entries = + entries_of(run(&drive, &contract, &pins, &[], false).expect("the read succeeds")); + assert_eq!( + entries, + vec![RankedEntry { + in_key: Some(IDENTITY_X.to_vec()), + key: b"art".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(90, 1)), + }], + "only the existing branch is bounded; the absent one is empty, not an error" + ); + + assert_proof_round_trips(&drive, &contract, &pins, &[], &entries); + } } diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs index 78b5e586538..f989bd5042f 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/execute_top_k.rs @@ -26,8 +26,11 @@ impl DriveDocumentRankedQuery<'_> { /// the direction and the tie contract. /// /// Fewer than `k` entries is normal (the index simply has fewer - /// groups than `offset + k`) and is not an error. A missing path - /// *is* an error rather than an empty result: the indexed + /// groups than `offset + k`) and is not an error. On an `IN`-pinned + /// request, an element whose prefix was never written contributes + /// an **empty branch** (union semantics). A missing path under a + /// single `==` pin — or under a *present* branch key — *is* an + /// error rather than an empty result: the indexed /// property-name tree is created when the contract is registered, so /// its absence means the contract-level state is not what the /// request claims, not that the ranking is empty. (An index with no @@ -55,9 +58,18 @@ impl DriveDocumentRankedQuery<'_> { // One walk per branch, each fetching a full page (the merge // lemma needs every branch's own top-k), merged with the // shared comparator. `offset` is grammar-rejected with `IN`, - // so `skipped` is always 0 here. + // so `skipped` is always 0 here. An `IN` element whose + // prefix was never written contributes the empty page — + // union semantics, decided at the branching Merk exactly + // like the proved path's authenticated absence (deeper + // breakage under a *present* key stays an error, and the + // single-`==`-pin contract is untouched: there, an unknown + // value is still an error, not an empty page). let per_branch = (0..self.prefix_branches.len()) .map(|branch| { + if self.branch_is_absent(branch, drive, transaction, platform_version)? { + return Ok(Vec::new()); + } Ok(self .execute_top_k_no_proof_branch( branch, @@ -82,6 +94,31 @@ impl DriveDocumentRankedQuery<'_> { self.execute_top_k_no_proof_branch(0, drive, transaction, platform_version) } + /// Whether this branch's key is absent at the branching Merk — the + /// union's empty-set case. Mirrors the proved path, where grovedb + /// authenticates the same absence at the same level. + pub(crate) fn branch_is_absent( + &self, + branch: usize, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let grove_version = &platform_version.drive.grove_version; + let paths = (0..self.prefix_branches.len()) + .map(|b| self.indexed_property_name_tree_path(b)) + .collect::, Error>>()?; + let (prefix, keys, _suffix) = super::branches::decompose_branch_paths(&paths)?; + let prefix_refs: Vec<&[u8]> = prefix.iter().map(|s| s.as_slice()).collect(); + let CostContext { value, cost: _ } = drive.grove.get_raw_optional( + prefix_refs.as_slice().into(), + &keys[branch], + transaction, + grove_version, + ); + Ok(value.map_err(|e| Error::GroveDB(Box::new(e)))?.is_none()) + } + /// One branch's page — the entire pre-`IN` executor, parameterized /// by which prefix branch's terminal tree it walks. fn execute_top_k_no_proof_branch( diff --git a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs index 964c01228b0..dedc79faa76 100644 --- a/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_ranked_query/tests.rs @@ -2907,6 +2907,51 @@ mod pinned_prefix { ); } + /// An `IN` element whose prefix was never written contributes the + /// **empty branch** — union semantics — while the single-`==`-pin + /// contract keeps erroring on an unknown value (pinned separately + /// by `unknown_prefix_value_errors_rather_than_fabricating_an_empty_page`). + /// The proved path authenticates the absence inside the branched + /// envelope, so read, proof, and verification agree. + #[test] + fn an_absent_in_element_contributes_an_empty_branch() { + let (drive, contract) = setup_grades_compound_ranked(); + insert_grades(&drive, &contract, &[(IDENTITY_X, "art", 90)]); + + let never_written = [9u8; 32]; + let pins = in_pin(&[IDENTITY_X, never_written]); + let page = match run(&drive, &contract, &pins, 2, false).expect("read succeeds") { + DocumentRankedResponse::Entries(page) => page, + DocumentRankedResponse::Proof(_) => panic!("expected entries, got a proof"), + }; + assert_eq!( + page.entries, + vec![RankedEntry { + in_key: Some(IDENTITY_X.to_vec()), + key: b"art".to_vec(), + value: RankedEntryValue::AvgFixedPoint(compute_avg_fixed_point(90, 1)), + }], + "only the existing branch contributes; the absent one is empty, not an error" + ); + + let proof = match run(&drive, &contract, &pins, 2, true).expect("prove succeeds") { + DocumentRankedResponse::Proof(proof) => proof, + DocumentRankedResponse::Entries(_) => panic!("expected a proof, got entries"), + }; + let (root_hash, verified) = client_side_query(&contract, &pins, 2) + .verify_ranked_top_k_proof(&proof, platform_version()) + .expect("the envelope authenticates the absent branch"); + assert_eq!(verified.entries, page.entries); + assert_eq!( + root_hash, + drive + .grove + .root_hash(None, &platform_version().drive.grove_version) + .unwrap() + .expect("root hash must be readable"), + ); + } + /// An unpinned request over the compound-only contract has no /// covering index — there is no global cross-prefix ordering to /// serve, so the rejection names the missing coverage. diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index c0dc25e228c..1d83c19ac43 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" thiserror = { version = "2.0.12" } bincode = { version = "=2.0.1" } versioned-feature-core = { git = "https://github.com/dashpay/versioned-feature-core", version = "1.0.0" } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864" } [features] mock-versions = [] diff --git a/packages/rs-platform-wallet/Cargo.toml b/packages/rs-platform-wallet/Cargo.toml index d6b59f25ac6..bb6670a0dba 100644 --- a/packages/rs-platform-wallet/Cargo.toml +++ b/packages/rs-platform-wallet/Cargo.toml @@ -69,7 +69,7 @@ zeroize = "1" log = "0.4" # Shielded pool (optional, behind `shielded` feature) -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", optional = true } # Direct `rusqlite` access so `FileBackedShieldedStore::open_path` can set # WAL + synchronous=NORMAL pragmas before handing the connection to # `ClientPersistentCommitmentTree`. Version locked to match the rev grovedb diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index cb90a8b234a..0b657f5d499 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -18,7 +18,7 @@ drive = { path = "../rs-drive", default-features = false, features = [ ] } drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dd2004e4eb0643a081356c0468132026217d7d66", features = [ +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "1d07f587a33b8e2a131c483f0c889ce7ab585864", features = [ "client", "sqlite", ], optional = true }